Browse Source

v1.0.0开发:登录页面开发

maijinpei 3 years ago
parent
commit
81cc47a0d4
96 changed files with 3600 additions and 231 deletions
  1. 2 2
      demo/build.gradle
  2. 42 1
      demo/src/main/AndroidManifest.xml
  3. 16 0
      demo/src/main/assets/yyxx_game/yyxx_cfg.properties
  4. 0 121
      demo/src/main/java/com/yyxx/columbus/demo/DemoActivity.kt
  5. 101 0
      demo/src/main/java/com/yyxxgame/columbus/DemoActivity.kt
  6. 1 1
      demo/src/main/java/com/yyxxgame/columbus/DemoApplication.kt
  7. 55 0
      demo/src/main/java/com/yyxxgame/columbus/EnvActivity.kt
  8. 1 1
      demo/src/main/java/com/yyxxgame/columbus/Item.kt
  9. 1 1
      demo/src/main/java/com/yyxxgame/columbus/WelcomeActivity.kt
  10. 8 3
      keystore.properties
  11. 11 0
      library_base/src/main/java/cn/yyxx/columbus/Version.kt
  12. 342 4
      library_base/src/main/java/cn/yyxx/columbus/base/Columbus.kt
  13. 47 1
      library_base/src/main/java/cn/yyxx/columbus/base/SdkBridgeManager.kt
  14. 1 1
      library_base/src/main/java/cn/yyxx/columbus/base/entity/Function.kt
  15. 29 0
      library_base/src/main/java/cn/yyxx/columbus/base/entity/SdkChargeInfo.kt
  16. 23 0
      library_base/src/main/java/cn/yyxx/columbus/base/entity/SdkRoleInfo.kt
  17. 10 0
      library_base/src/main/java/cn/yyxx/columbus/base/internal/IInitialize.kt
  18. 68 0
      library_base/src/main/java/cn/yyxx/columbus/base/utils/ParamsUtils.kt
  19. 1 1
      library_core/CMakeLists.txt
  20. 18 2
      library_core/build.gradle
  21. 26 0
      library_core/src/main/AndroidManifest.xml
  22. 12 13
      library_core/src/main/cpp/aes_utils.cpp
  23. 40 0
      library_core/src/main/cpp/base64_utils.cpp
  24. 22 0
      library_core/src/main/cpp/include/base64_utils.h
  25. 3 3
      library_core/src/main/cpp/include/rsa/rsa_utils.h
  26. 4 36
      library_core/src/main/cpp/rsa_utils.cpp
  27. 22 6
      library_core/src/main/cpp/sdk_drive.cpp
  28. 0 11
      library_core/src/main/java/cn/yyxx/columbus/Version.kt
  29. 101 1
      library_core/src/main/java/cn/yyxx/columbus/core/SdkBridge.kt
  30. 0 22
      library_core/src/main/java/cn/yyxx/columbus/core/SdkDrive.kt
  31. 24 0
      library_core/src/main/java/cn/yyxx/columbus/core/entity/ClickType.kt
  32. 14 0
      library_core/src/main/java/cn/yyxx/columbus/core/entity/LoginType.kt
  33. 50 0
      library_core/src/main/java/cn/yyxx/columbus/core/entity/SdkBackLoginInfo.kt
  34. 97 0
      library_core/src/main/java/cn/yyxx/columbus/core/entity/bean/init/FloatCfg.kt
  35. 102 0
      library_core/src/main/java/cn/yyxx/columbus/core/entity/bean/init/InitBean.kt
  36. 180 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/SdkBridgeImpl.kt
  37. 50 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/SdkDrive.kt
  38. 90 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/iab/InAppBilling.kt
  39. 287 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/login/LoginActivity.kt
  40. 40 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/login/LoginFragmentPagerAdapter.kt
  41. 137 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/login/UserSignInImpl.kt
  42. 177 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/login/fragment/LauncherFragment.kt
  43. 141 0
      library_core/src/main/java/cn/yyxx/columbus/core/impl/login/fragment/RegisterFragment.kt
  44. 19 0
      library_core/src/main/java/cn/yyxx/columbus/core/internal/IEventObserver.kt
  45. 10 0
      library_core/src/main/java/cn/yyxx/columbus/core/internal/IImplCallback.kt
  46. 45 0
      library_core/src/main/java/cn/yyxx/columbus/core/linking/Linking.kt
  47. 27 0
      library_core/src/main/java/cn/yyxx/columbus/core/linking/channel/LinkingAdjustImpl.kt
  48. 26 0
      library_core/src/main/java/cn/yyxx/columbus/core/linking/channel/LinkingFirebaseImpl.kt
  49. 45 0
      library_core/src/main/java/cn/yyxx/columbus/core/network/Host.kt
  50. 58 0
      library_core/src/main/java/cn/yyxx/columbus/core/ui/EventEditText.kt
  51. 29 0
      library_core/src/main/java/cn/yyxx/columbus/core/ui/NoScrollViewPager.kt
  52. 86 0
      library_core/src/main/java/cn/yyxx/columbus/core/ui/dialog/AgreementDialog.kt
  53. 58 0
      library_core/src/main/java/cn/yyxx/columbus/core/ui/dialog/ChooseLoginDialog.kt
  54. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_account_img.png
  55. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_account_login_img.png
  56. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_check_img.png
  57. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_facebook_img.png
  58. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_facebook_login_img.png
  59. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_google_img.png
  60. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_google_login_img.png
  61. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_guest_img.png
  62. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_guest_login_img.png
  63. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_hide_img.png
  64. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_pack_down_img.png
  65. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_pack_up_img.png
  66. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_pwd_img.png
  67. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_return_img.png
  68. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_show_img.png
  69. BIN
      library_core/src/main/res/drawable-xhdpi/yyxx_uncheck_img.png
  70. 5 0
      library_core/src/main/res/drawable/yyxx_btn_black_bg.xml
  71. 5 0
      library_core/src/main/res/drawable/yyxx_btn_blue_bg.xml
  72. 5 0
      library_core/src/main/res/drawable/yyxx_btn_green_bg.xml
  73. 5 0
      library_core/src/main/res/drawable/yyxx_btn_green_blue_bg.xml
  74. 8 0
      library_core/src/main/res/drawable/yyxx_btn_white_bg.xml
  75. 9 0
      library_core/src/main/res/drawable/yyxx_et_frame_focused_bg.xml
  76. 9 0
      library_core/src/main/res/drawable/yyxx_et_frame_normal_bg.xml
  77. 5 0
      library_core/src/main/res/drawable/yyxx_et_frame_selector_bg.xml
  78. 7 0
      library_core/src/main/res/drawable/yyxx_login_panel_bg.xml
  79. 8 0
      library_core/src/main/res/drawable/yyxx_tab_left_select.xml
  80. 8 0
      library_core/src/main/res/drawable/yyxx_tab_left_selected.xml
  81. 8 0
      library_core/src/main/res/drawable/yyxx_tab_right_select.xml
  82. 8 0
      library_core/src/main/res/drawable/yyxx_tab_right_selected.xml
  83. 8 0
      library_core/src/main/res/drawable/yyxx_webview_border.xml
  84. 59 0
      library_core/src/main/res/layout/yyxx_agreement_dialog.xml
  85. 221 0
      library_core/src/main/res/layout/yyxx_choose_login_dialog.xml
  86. 70 0
      library_core/src/main/res/layout/yyxx_event_edit_text.xml
  87. 44 0
      library_core/src/main/res/layout/yyxx_login.xml
  88. 135 0
      library_core/src/main/res/layout/yyxx_login_launcher.xml
  89. 82 0
      library_core/src/main/res/layout/yyxx_login_register.xml
  90. 21 0
      library_core/src/main/res/values/yyxx_colors.xml
  91. 32 0
      library_core/src/main/res/values/yyxx_strings.xml
  92. 16 0
      library_core/src/main/res/values/yyxx_styles.xml
  93. 1 0
      settings.gradle
  94. 22 0
      test.pem
  95. BIN
      zkeystore/demo_yyxx.keystore
  96. BIN
      zkeystore/demo_yyxx_backup.keystore

+ 2 - 2
demo/build.gradle

@@ -12,7 +12,7 @@ android {
     buildToolsVersion BUILD_TOOLS_VERSION
 
     defaultConfig {
-        applicationId "com.yyxx.columbus.demo"
+        applicationId "com.yyxxgame.columbus"
         minSdkVersion MIN_SDK_VERSION
         targetSdkVersion TARGET_SDK_VERSION
         versionCode 1
@@ -68,5 +68,5 @@ android {
 
 dependencies {
 
-    implementation project(':library_core')
+    api project(':library_core')
 }

+ 42 - 1
demo/src/main/AndroidManifest.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.yyxx.columbus.demo">
+    package="com.yyxxgame.columbus">
 
     <application
         android:name=".DemoApplication"
@@ -35,6 +35,47 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+
+        <activity
+            android:name=".EnvActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+            android:exported="true"
+            android:launchMode="singleTask"
+            android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- Facebook start -->
+        <meta-data
+            android:name="com.facebook.sdk.ApplicationId"
+            android:value="\1047370039003298" />
+
+        <activity
+            android:name="com.facebook.FacebookActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" />
+
+        <activity
+            android:name="com.facebook.CustomTabActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+
+                <data android:scheme="fb1047370039003298" />
+            </intent-filter>
+        </activity>
+
+        <!-- Facebook 分享 -->
+        <!--        <provider-->
+        <!--            android:name="com.facebook.FacebookContentProvider"-->
+        <!--            android:authorities="com.facebook.app.FacebookContentProvider283753472796552"-->
+        <!--            android:exported="true" />-->
+        <!-- Facebook end -->
     </application>
 
 </manifest>

+ 16 - 0
demo/src/main/assets/yyxx_game/yyxx_cfg.properties

@@ -0,0 +1,16 @@
+#出包版本
+YYXX_GCP_CODE=20201010
+#分包标识
+YYXX_GAME_CODE=9y12un3y
+# 事件打点应用ID
+YYXX_ADJUST_APP_ID=3lb7knrx3yww
+# 事件打点开关,没配置的情况下默认开启(true)
+#YYXX_ADJUST_ENABLE=false
+# Google AppId
+YYXX_GOOGLE_APP_ID=633652677873
+# Google Server Client Id
+YYXX_GOOGLE_CLIENT_ID=633652677873-m2f480tq9t2elrvit98vf3nsbleo1pab.apps.googleusercontent.com
+# Facebook AppId
+YYXX_FACEBOOK_ID=1047370039003298
+#debug模式(cp出正式包请关闭)
+YYXX_OWN_DEBUG=true

+ 0 - 121
demo/src/main/java/com/yyxx/columbus/demo/DemoActivity.kt

@@ -1,121 +0,0 @@
-package com.yyxx.columbus.demo
-
-import android.app.Activity
-import android.os.Bundle
-import android.os.Handler
-import android.os.Looper
-import android.os.Message
-import android.view.View
-import android.widget.*
-import cn.yyxx.columbus.base.utils.Logger
-import cn.yyxx.columbus.core.SdkDrive
-
-/**
- * @author #Suyghur.
- * Created on 2021/06/09
- */
-class DemoActivity : Activity(), View.OnClickListener {
-
-    private val events = arrayListOf(
-        Item(0, "00 接口环境切换"),
-        Item(1, "01 登录"),
-        Item(2, "02 切换账号"),
-        Item(3, "03 角色创建上报"),
-        Item(4, "04 角色登录上报"),
-        Item(5, "05 角色升级上报"),
-        Item(6, "06 定额充值"),
-        Item(7, "07 绑定平台账号"),
-        Item(8, "08 打开客服中心"),
-        Item(9, "09 崩溃测试")
-    )
-
-
-    private lateinit var layout: LinearLayout
-    private lateinit var mTextView: TextView
-
-    private val handler = object : Handler(Looper.getMainLooper()) {
-        override fun handleMessage(msg: Message) {
-            when (msg.what) {
-                10001 -> {
-                    with(mTextView) {
-                        text = text.toString() + msg.obj.toString()
-                    }
-                }
-            }
-        }
-    }
-
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        initView()
-    }
-
-    private fun initView() {
-        layout = LinearLayout(this)
-        layout.orientation = LinearLayout.VERTICAL
-        initButton()
-        mTextView = TextView(this)
-        with(mTextView) {
-            text = ""
-            this@DemoActivity.layout.addView(this)
-        }
-        val scrollView = ScrollView(this)
-        scrollView.addView(layout)
-        setContentView(scrollView)
-    }
-
-
-    private fun initButton() {
-        for (event in events) {
-            with(Button(this)) {
-                text = event.name
-                tag = event.id
-                id = event.id
-                setOnClickListener(this@DemoActivity)
-                this@DemoActivity.layout.addView(this)
-            }
-        }
-    }
-
-    override fun onClick(v: View?) {
-        v?.apply {
-            when (tag as Int) {
-                0 -> SdkDrive.getAesKey()
-                1 -> {
-                    val src =
-                        "{\"balance\":\"600\",\"common\":{\"biz\":{\"game_code\":\"testcode123456\",\"package_name\":\"com.flyfun.demo\"},\"device\":{\"adid\":\"902c95bcd33f7a83\",\"android_id\":\"902c95bcd33f7a83\",\"device_id\":\"902c95bcd33f7a83\",\"idfa\":\"\",\"idfv\":\"\",\"imei\":\"0\",\"local_language\":\"CN\",\"mac\":\"02:00:00:00:00:00\",\"mfrs\":\"HUAWEI\",\"mobile_brand\":\"HUAWEI\",\"model\":\"ANG-AN00\",\"network\":\"0\",\"os\":\"android\",\"os_version\":\"10\",\"screen\":\"1080x2340\",\"simulator\":\"0\"},\"ext\":\"\",\"vers\":{\"client_version\":\"1.1.7\",\"game_version_code\":\"104\",\"game_version_name\":\"1.0.4\",\"server_version\":\"1.0.0\"}},\"role_id\":\"aaa1623318283872\",\"role_level\":\"110\",\"role_name\":\"角色名123\",\"server_code\":\"333\",\"server_name\":\"服务器名333\",\"user_id\":\"920404284947132416\",\"vip_level\":\"1\"}"
-                    Logger.d(src)
-                    val raw = SdkDrive.aesEncrypt(src)
-                    Logger.d(raw)
-                }
-                2 -> {
-                    val src =
-                        "d76f64c2c5e39d75300f90dfb7b2750400df44ff95fa768f41356e468dde2f47176b6051d88b1ce61940d7ec6173f19950220c2ac8aa7b3a2df65d95565c4858a7511d266713075257f11e0833f91fcb4fa19bff80aec5cc621a1d85c3935e2a1ef1ac71f8ec58851eaee7716e3c08829274965b16c33c234d9777541f70d6168b59e07f2d8e61d3babd4fcc13e907671a427884ae16db0a6b1922b17223414d505624f669435128b0bb6b15f3ec2b3ad088bb61ca67c370bfbd39114213a1809a83f36384b2953e6d00a9c8bdf1ddadd9caa74c35edba1262825baaee1181e8620c75ef9a8cf5f5d5c510a3da32b6f5ebb25657eab693047236c9faec7cc985f6592be9d5f90936a4a9b5e1bfaea93de5bd53f8b74de33e79e5f2b140220accf31db6db066b5019598f4a7127a01b77bb6c65c443c9a11b0a36f63f598b2cfa68c77ea6ad6deda17c70a05f955efb5d4a8f12271947ec02a8305e8a265ed5e1924949bcafddce8c7c0eaa2e90fd3750ad58909ce5c6c13ca87d83be367b6a1ee884659d776a37a0bda19656c30ac948ca604e551bf687512eba6a35aedec9cb8b615abbb8f9b8cd042eccbf46e4b9abd763a7012e761913fdb3a9421d83a764dc8600a1ec92f12f58da5904edb3cdb1da10807aa111e39a0e7117d0fc0bbd7a4f84d22ac996f8f94288f6af0e8cfa5091f08bb73fbaa335c77b3e41dd321130c8c69bf81e76e3b3b1d006a2f03de86f9fb85a0b970f1512aaf0b0a0613258ccea443acbe57ab057bb2a9d6fb109282cce9e1f8bba9128b324f845f9da632c85e670b88d9a570e08b7d59d2886a737b0d8f6ae81e6c0beddf2a8d628f3ea33f6a7320b0da95feabe6a4a617ddc804f6f1813ecbf05b274281612de88f57746ffa52c5ee6a6b8a5db41b07ab9b5adffbb8b0f0f721cc9484a9d7997da6710b1f583decf7b897c3763f73ef3a8e43cfff297348dd3ca4ffb30a99a91049951710d6fbc55107cee3359f08e39494884a661"
-                    val key = "qtfc2jsgqrz81inn"
-                    val src2 = SdkDrive.aesDecrypt(src, key)
-                    Logger.d(src2)
-                }
-                3 -> {
-                    val src = "qtfc2jsgqrz81inn"
-                    val raw = SdkDrive.rsaEncrypt(src)
-                    Logger.d("raw : $raw")
-                }
-                4 -> {
-                    val raw =
-                        "ItBGaPY+GvPqtWg/BVVt6GQuhRI7NF8LC9qxl+0R2+5plJ2V5HBXOol8OSEMWttzRV/pbPaOYMoVjma67Js5LEe2RrL/vc84w2updiMHqAIjtMu6rXmIs1zHlCeXf1uaW8SGuKsM9Xn1OQ6GundkbinIOSVefn+Z/MkHeu446xU="
-                    val src = SdkDrive.rsaDecrypt(raw)
-                    Logger.d("src : $src")
-                }
-//                5 -> {
-//                    val raw =
-//                        "eyJiYWxhbmNlIjoiNjAwIiwiY29tbW9uIjp7ImJpeiI6eyJnYW1lX2NvZGUiOiJ0ZXN0Y29kZTEyMzQ1NiIsInBhY2thZ2VfbmFtZSI6ImNvbS5mbHlmdW4uZGVtbyJ9LCJkZXZpY2UiOnsiYWRpZCI6IjkwMmM5NWJjZDMzZjdhODMiLCJhbmRyb2lkX2lkIjoiOTAyYzk1YmNkMzNmN2E4MyIsImRldmljZV9pZCI6IjkwMmM5NWJjZDMzZjdhODMiLCJpZGZhIjoiIiwiaWRmdiI6IiIsImltZWkiOiIwIiwibG9jYWxfbGFuZ3VhZ2UiOiJDTiIsIm1hYyI6IjAyOjAwOjAwOjAwOjAwOjAwIiwibWZycyI6IkhVQVdFSSIsIm1vYmlsZV9icmFuZCI6IkhVQVdFSSIsIm1vZGVsIjoiQU5HLUFOMDAiLCJuZXR3b3JrIjoiMCIsIm9zIjoiYW5kcm9pZCIsIm9zX3ZlcnNpb24iOiIxMCIsInNjcmVlbiI6IjEwODB4MjM0MCIsInNpbXVsYXRvciI6IjAifSwiZXh0IjoiIiwidmVycyI6eyJjbGllbnRfdmVyc2lvbiI6IjEuMS43IiwiZ2FtZV92ZXJzaW9uX2NvZGUiOiIxMDQiLCJnYW1lX3ZlcnNpb25fbmFtZSI6IjEuMC40Iiwic2VydmVyX3ZlcnNpb24iOiIxLjAuMCJ9fSwicm9sZV9pZCI6ImFhYTE2MjMzMTgyODM4NzIiLCJyb2xlX2xldmVsIjoiMTEwIiwicm9sZV9uYW1lIjoi6KeS6Imy5ZCNMTIzIiwic2VydmVyX2NvZGUiOiIzMzMiLCJzZXJ2ZXJfbmFtZSI6IuacjeWKoeWZqOWQjTMzMyIsInVzZXJfaWQiOiI5MjA0MDQyODQ5NDcxMzI0MTYiLCJ2aXBfbGV2ZWwiOiIxIn0K"
-//                    val src = SdkDrive.base64Decode(raw)
-//                    Logger.d("src : $src")
-//                }
-            }
-        }
-    }
-
-
-}

+ 101 - 0
demo/src/main/java/com/yyxxgame/columbus/DemoActivity.kt

@@ -0,0 +1,101 @@
+package com.yyxxgame.columbus
+
+import android.app.Activity
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.view.View
+import android.widget.*
+import cn.yyxx.columbus.base.Columbus
+import cn.yyxx.columbus.base.internal.ICallback
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/09
+ */
+class DemoActivity : Activity(), View.OnClickListener {
+
+    private val events = arrayListOf(
+        Item(0, "00 接口环境切换"),
+        Item(1, "01 登录"),
+        Item(2, "02 切换账号"),
+        Item(3, "03 角色创建上报"),
+        Item(4, "04 角色登录上报"),
+        Item(5, "05 角色升级上报"),
+        Item(6, "06 定额充值"),
+        Item(7, "07 绑定平台账号"),
+        Item(8, "08 打开客服中心"),
+        Item(9, "09 崩溃测试")
+    )
+
+
+    private lateinit var layout: LinearLayout
+    private lateinit var mTextView: TextView
+
+    private val handler = object : Handler(Looper.getMainLooper()) {
+        override fun handleMessage(msg: Message) {
+            when (msg.what) {
+                10001 -> {
+                    with(mTextView) {
+                        text = text.toString() + msg.obj.toString()
+                    }
+                }
+            }
+        }
+    }
+
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        Columbus.getInstance().initialize(this, true, object : ICallback {
+            override fun onResult(code: Int, result: String) {
+            }
+        })
+        initView()
+    }
+
+    private fun initView() {
+        layout = LinearLayout(this)
+        layout.orientation = LinearLayout.VERTICAL
+        initButton()
+        mTextView = TextView(this)
+        with(mTextView) {
+            text = ""
+            this@DemoActivity.layout.addView(this)
+        }
+        val scrollView = ScrollView(this)
+        scrollView.addView(layout)
+        setContentView(scrollView)
+    }
+
+
+    private fun initButton() {
+        for (event in events) {
+            with(Button(this)) {
+                text = event.name
+                tag = event.id
+                id = event.id
+                setOnClickListener(this@DemoActivity)
+                this@DemoActivity.layout.addView(this)
+            }
+        }
+    }
+
+    override fun onClick(v: View?) {
+        v?.apply {
+            when (tag as Int) {
+                0 -> EnvActivity.start(this@DemoActivity)
+                1 -> {
+                    Columbus.getInstance().login(this@DemoActivity, true, object : ICallback {
+                        override fun onResult(code: Int, result: String) {
+
+                        }
+                    })
+                }
+            }
+        }
+    }
+
+
+}

+ 1 - 1
demo/src/main/java/com/yyxx/columbus/demo/DemoApplication.kt → demo/src/main/java/com/yyxxgame/columbus/DemoApplication.kt

@@ -1,4 +1,4 @@
-package com.yyxx.columbus.demo
+package com.yyxxgame.columbus
 
 import android.content.Context
 import cn.yyxx.columbus.base.ColumbusApplication

+ 55 - 0
demo/src/main/java/com/yyxxgame/columbus/EnvActivity.kt

@@ -0,0 +1,55 @@
+package com.yyxxgame.columbus
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import android.widget.LinearLayout
+import cn.yyxx.support.HostModelUtils
+import cn.yyxx.support.hawkeye.ToastUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class EnvActivity : Activity(), View.OnClickListener {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        with(LinearLayout(this)) {
+
+            orientation = LinearLayout.VERTICAL
+
+            val btnTest = Button(this@EnvActivity)
+            btnTest.text = "00 测试环境"
+            btnTest.tag = HostModelUtils.ENV_TEST
+            btnTest.setOnClickListener(this@EnvActivity)
+            addView(btnTest)
+
+            val btnOnline = Button(this@EnvActivity)
+            btnOnline.text = "01 线上环境"
+            btnOnline.tag = HostModelUtils.ENV_ONLINE
+            btnOnline.setOnClickListener(this@EnvActivity)
+            addView(btnOnline)
+
+            setContentView(this)
+        }
+
+    }
+
+    override fun onClick(v: View?) {
+        v?.apply {
+            HostModelUtils.setHostModel(this@EnvActivity, tag as Int)
+            ToastUtils.toastInfo(this@EnvActivity, "接口环境切换成功,重启应用后生效")
+        }
+    }
+
+    companion object {
+        fun start(activity: Activity) {
+            activity.startActivity(Intent(activity, EnvActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+        }
+    }
+
+}

+ 1 - 1
demo/src/main/java/com/yyxx/columbus/demo/Item.kt → demo/src/main/java/com/yyxxgame/columbus/Item.kt

@@ -1,4 +1,4 @@
-package com.yyxx.columbus.demo
+package com.yyxxgame.columbus
 
 /**
  * @author #Suyghur,

+ 1 - 1
demo/src/main/java/com/yyxx/columbus/demo/WelcomeActivity.kt → demo/src/main/java/com/yyxxgame/columbus/WelcomeActivity.kt

@@ -1,4 +1,4 @@
-package com.yyxx.columbus.demo
+package com.yyxxgame.columbus
 
 import android.app.Activity
 import android.content.Intent

+ 8 - 3
keystore.properties

@@ -1,5 +1,10 @@
 #demo
-storePassword=demo53ux_yyxx2021
-keyPassword=demo53ux_yyxx2021
+storePassword=demo6ztv_yyxx2021
+keyPassword=demo6ztv_yyxx2021
 keyAlias=alias.demo_yyxx2021
-storeFile=../zkeystore/demo_yyxx.keystore
+storeFile=../zkeystore/demo_yyxx.keystore
+
+#storePassword=demo53ux_yyxx2021
+#keyPassword=demo53ux_yyxx2021
+#keyAlias=alias.demo_yyxx2021
+#storeFile=../zkeystore/demo_yyxx_backup.keystore

+ 11 - 0
library_base/src/main/java/cn/yyxx/columbus/Version.kt

@@ -0,0 +1,11 @@
+package cn.yyxx.columbus
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/09
+ */
+object Version {
+    const val VERSION_NAME = "1.0.0"
+    const val VERSION_CODE = 100
+    const val SERVER_VERSION = "1.0.0"
+}

+ 342 - 4
library_base/src/main/java/cn/yyxx/columbus/base/Columbus.kt

@@ -3,8 +3,19 @@ package cn.yyxx.columbus.base
 import android.app.Activity
 import android.app.Application
 import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.text.TextUtils
+import android.webkit.WebView
 import androidx.annotation.Keep
+import cn.yyxx.columbus.Version
+import cn.yyxx.columbus.base.entity.Function
+import cn.yyxx.columbus.base.entity.SdkChargeInfo
+import cn.yyxx.columbus.base.entity.SdkRoleInfo
 import cn.yyxx.columbus.base.internal.ICallback
+import cn.yyxx.columbus.base.internal.IInitialize
+import cn.yyxx.columbus.base.utils.Logger
+import cn.yyxx.support.AppUtils
 
 /**
  * @author #Suyghur.
@@ -12,30 +23,357 @@ import cn.yyxx.columbus.base.internal.ICallback
  */
 class Columbus private constructor() {
 
+    private var mSdkBridge: Any? = null
+    private var processName: String = ""
+    private var clickLoginTime = 0L
+    private var clickLogoutTime = 0L
+    private var clickChargeTime = 0L
 
-    fun attachBaseContext(application: Application, context: Context) {
+    private var doSdkInit = false
+
+    private fun getSdkBridgeManager(context: Context): Any? {
+        if (mSdkBridge == null) {
+            mSdkBridge = SdkBridgeManager.initSdkBridgeManager(context)
+        }
+        return mSdkBridge
+    }
 
+    /**
+     * 同步Application中的attachBaseContext
+     */
+    fun attachBaseContext(application: Application, context: Context) {
+        if (TextUtils.isEmpty(processName)) {
+            this.processName = AppUtils.getProcessName(application)
+        }
+        if (TextUtils.isEmpty(processName) || processName != context.packageName) {
+            return
+        }
+        if (mSdkBridge == null) {
+            mSdkBridge = getSdkBridgeManager(application)
+        }
+        SdkBridgeManager.call(Function.ATTACH_BASE_CONTEXT, arrayOf(Application::class.java, Context::class.java), arrayOf(application, context))
     }
 
 
+    /**
+     * 同步Application中的onCreate
+     */
     fun initApplication(application: Application) {
-
+        if (TextUtils.isEmpty(processName)) {
+            this.processName = AppUtils.getProcessName(application)
+        }
+        //处理Android P webView的坑
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            try {
+                if (application.packageName != processName) {
+                    WebView.setDataDirectorySuffix(processName)
+                }
+            } catch (e: Exception) {
+                e.printStackTrace()
+            }
+        }
+        if (TextUtils.isEmpty(processName) || processName != application.packageName) {
+            return
+        }
+        if (mSdkBridge == null) {
+            mSdkBridge = getSdkBridgeManager(application)
+        }
+        SdkBridgeManager.call(Function.INIT_APPLICATION, arrayOf(Application::class.java), arrayOf(application))
     }
 
+    /**
+     * SDK初始化
+     *
+     * @param activity    Activity上下文
+     * @param isLandscape 是否横屏
+     * @param callback    SDK初始化回调
+     */
     fun initialize(activity: Activity, isLandscape: Boolean, callback: ICallback) {
+        if (checkSdkBridgeNull(Function.INITIALIZE, callback)) {
+            return
+        }
 
+        //有些CP在资源再加时候回重复调用初始化,这里拦截一下
+        if (doSdkInit) {
+            Logger.e("Columbus initialize 已经执行,拦截此次调用")
+            return
+        }
+
+        val initCallback = object : IInitialize {
+            override fun onResult(code: Int, msg: String) {
+                doSdkInit = code == 0
+            }
+        }
+
+        SdkBridgeManager.call(
+            Function.INITIALIZE,
+            arrayOf(Activity::class.java, Boolean::class.java, ICallback::class.java, IInitialize::class.java),
+            arrayOf(activity, isLandscape, callback, initCallback)
+        )
     }
 
-    fun login(activity: Activity, callback: ICallback) {
+    /**
+     * SDK用户登录
+     *
+     * @param activity Activity上下文
+     * @param isAutoLogin 是否自动登录
+     * @param callback 登录回调对象
+     */
+    fun login(activity: Activity, isAutoLogin: Boolean, callback: ICallback) {
+        if (checkSdkBridgeNull(Function.LOGIN, callback)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.LOGIN, callback)) {
+            return
+        }
 
+        if (System.currentTimeMillis() - clickLoginTime < CLICK_INTERVAL) {
+            Logger.e("调用登录接口太频繁,拦截此次操作")
+            return
+        }
+
+        clickLoginTime = System.currentTimeMillis()
+        SdkBridgeManager.call(
+            Function.LOGIN,
+            arrayOf(Activity::class.java, Boolean::class.java, ICallback::class.java),
+            arrayOf(activity, isAutoLogin, callback)
+        )
     }
 
+    /**
+     * SDK用户登出账号
+     *
+     * @param activity Activity上下文
+     * @param callback 登出回调对象
+     */
     fun logout(activity: Activity, callback: ICallback) {
+        if (checkSdkBridgeNull(Function.LOGOUT, callback)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.LOGOUT, callback)) {
+            return
+        }
+
+        if (System.currentTimeMillis() - clickLoginTime < CLICK_INTERVAL) {
+            Logger.e("调用登录接口后,调用登出账号接口间隔太短,拦截此次操作")
+            return
+        }
+
+        if (System.currentTimeMillis() - clickLogoutTime < CLICK_INTERVAL) {
+            Logger.e("调用登出账号接口太频繁,拦截此次操作")
+            return
+        }
+
+        clickLogoutTime = System.currentTimeMillis()
+        SdkBridgeManager.call(Function.LOGOUT, arrayOf(Activity::class.java, ICallback::class.java), arrayOf(activity, callback))
+    }
+
+    /**
+     * SDK用户支付
+     *
+     * @param activity   Activity上下文
+     * @param chargeInfo 支付信息实体对象
+     * @param callback   支付回调对象
+     */
+    fun charge(activity: Activity, chargeInfo: SdkChargeInfo, callback: ICallback) {
+        if (checkSdkBridgeNull(Function.CHARGE, callback)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.CHARGE, callback)) {
+            return
+        }
+
+        if (System.currentTimeMillis() - clickChargeTime < CLICK_INTERVAL) {
+            Logger.e("调用充值接口太频繁,拦截此次操作")
+            return
+        }
+
+        clickChargeTime = System.currentTimeMillis()
+        SdkBridgeManager.call(
+            Function.CHARGE,
+            arrayOf(Activity::class.java, SdkChargeInfo::class.java, ICallback::class.java),
+            arrayOf(activity, chargeInfo, callback)
+        )
+    }
+
+    /**
+     * SDK角色创建信息上报
+     *
+     * @param activity Activity上下文
+     * @param roleInfo 角色信息实体
+     */
+    fun roleCreate(activity: Activity, roleInfo: SdkRoleInfo) {
+        if (checkSdkBridgeNull(Function.ROLE_CREATE, null)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.ROLE_CREATE, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ROLE_CREATE, arrayOf(Activity::class.java, SdkRoleInfo::class.java), arrayOf(activity, roleInfo))
+    }
+
+    /**
+     * SDK角色登录信息上报
+     *
+     * @param activity Activity上下文
+     * @param roleInfo 角色信息实体
+     */
+    fun roleLauncher(activity: Activity, roleInfo: SdkRoleInfo) {
+        if (checkSdkBridgeNull(Function.ROLE_LAUNCHER, null)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.ROLE_LAUNCHER, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ROLE_LAUNCHER, arrayOf(Activity::class.java, SdkRoleInfo::class.java), arrayOf(activity, roleInfo))
+    }
+
+    /**
+     * SDK角色升级信息上报
+     *
+     * @param activity Activity上下文
+     * @param roleInfo 角色信息实体
+     */
+    fun roleLevelUp(activity: Activity, roleInfo: SdkRoleInfo) {
+        if (checkSdkBridgeNull(Function.ROLE_LEVEL_UP, null)) {
+            return
+        }
+
+        if (checkSdkNonInit(Function.ROLE_LEVEL_UP, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ROLE_LEVEL_UP, arrayOf(Activity::class.java, SdkRoleInfo::class.java), arrayOf(activity, roleInfo))
+    }
+
+    /**
+     * 显示退出框
+     *
+     * @param activity Activity上下文
+     * @param callback 退出回调对象
+     */
+    fun openExitView(activity: Activity, callback: ICallback) {
+        if (checkSdkBridgeNull(Function.OPEN_EXIT_VIEW, null)) {
+            return
+        }
 
+        if (checkSdkNonInit(Function.OPEN_EXIT_VIEW, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.OPEN_EXIT_VIEW, arrayOf(Activity::class.java, ICallback::class.java), arrayOf(activity, callback))
     }
 
-    fun charge(activity: Activity, callback: ICallback) {
+    fun onStart(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_START, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_START, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onRestart(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_RESTART, null)) {
+            return
+        }
 
+        SdkBridgeManager.call(Function.ON_RESTART, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onResume(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_RESUME, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_RESUME, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onPause(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_PAUSE, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_PAUSE, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onStop(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_STOP, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_STOP, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onDestroy(activity: Activity) {
+        if (checkSdkBridgeNull(Function.ON_DESTROY, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_DESTROY, arrayOf(Activity::class.java), arrayOf(activity))
+    }
+
+    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, intent: Intent) {
+        if (checkSdkBridgeNull(Function.ON_ACTIVITY_RESULT, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(
+            Function.ON_ACTIVITY_RESULT,
+            arrayOf(Activity::class.java, Int::class.java, Int::class.java, Intent::class.java),
+            arrayOf(activity, requestCode, resultCode, intent)
+        )
+    }
+
+    fun onNewIntent(activity: Activity, intent: Intent) {
+        if (checkSdkBridgeNull(Function.ON_START, null)) {
+            return
+        }
+
+        SdkBridgeManager.call(Function.ON_START, arrayOf(Activity::class.java, Intent::class.java), arrayOf(activity, intent))
+    }
+
+    fun getCurrentUserId(): String {
+        if (checkSdkBridgeNull(Function.GET_CURRENT_USER_ID, null)) {
+            return ""
+        }
+
+        if (checkSdkNonInit(Function.GET_CURRENT_USER_ID, null)) {
+            return ""
+        }
+
+        return SdkBridgeManager.callback(Function.GET_CURRENT_USER_ID, emptyArray(), emptyArray()) as String
+    }
+
+    fun getSdkVersion(): String {
+        return Version.VERSION_NAME
+    }
+
+
+    private fun checkSdkBridgeNull(function: String, callback: ICallback?): Boolean {
+        return if (mSdkBridge == null) {
+            Logger.e("invoke $function error ... SdkBridge is null")
+            callback?.onResult(-1, "Columbus 初始化失败")
+            true
+        } else {
+            false
+        }
+    }
+
+    private fun checkSdkNonInit(function: String, callback: ICallback?): Boolean {
+        return if (!doSdkInit) {
+            Logger.e("invoke $function error ... Columbus not initialized yet")
+            callback?.onResult(-1, "Columbus 还未进行初始化")
+            true
+        } else {
+            false
+        }
     }
 
     companion object {

+ 47 - 1
library_base/src/main/java/cn/yyxx/columbus/base/SdkBridgeManager.kt

@@ -1,8 +1,54 @@
 package cn.yyxx.columbus.base
 
+import android.content.Context
+import java.lang.reflect.Method
+
 /**
  * @author #Suyghur.
  * Created on 2021/06/12
  */
-class SdkBridgeManager {
+object SdkBridgeManager {
+
+    var sdkBridge: Any? = null
+    var clzBridge: Class<*>? = null
+
+    fun initSdkBridgeManager(context: Context?): Any? {
+        if (sdkBridge != null) {
+            return sdkBridge
+        }
+
+        try {
+            clzBridge = Class.forName("cn.yyxx.columbus.core.SdkBridge")
+            //获取构造函数的构造器
+            val constructor = clzBridge!!.getDeclaredConstructor(Context::class.java)
+            sdkBridge = constructor.newInstance(context)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        return sdkBridge
+    }
+
+    fun call(methodName: String, types: Array<Class<*>?>, values: Array<Any?>) {
+        try {
+            clzBridge?.apply {
+                val method: Method = this.getMethod(methodName, *types)
+                method.invoke(sdkBridge, *values)
+            }
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+        }
+    }
+
+
+    fun callback(methodName: String, types: Array<Class<*>?>, values: Array<Any?>): Any? {
+        try {
+            clzBridge?.let {
+                val method: Method = it.getMethod(methodName, *types)
+                return method.invoke(sdkBridge, *values)
+            }
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+        }
+        return null
+    }
 }

+ 1 - 1
library_base/src/main/java/cn/yyxx/columbus/base/entity/Function.kt

@@ -17,7 +17,7 @@ object Function {
     const val OPEN_GM_CENTER = "openGmCenter"
     const val ROLE_CREATE = "roleCreate"
     const val ROLE_LAUNCHER = "roleLauncher"
-    const val ROLE_UPGRADE = "roleUpgrade"
+    const val ROLE_LEVEL_UP = "roleLevelUp"
     const val ON_START = "onStart"
     const val ON_RESUME = "onResume"
     const val ON_RESTART = "onRestart"

+ 29 - 0
library_base/src/main/java/cn/yyxx/columbus/base/entity/SdkChargeInfo.kt

@@ -0,0 +1,29 @@
+package cn.yyxx.columbus.base.entity
+
+import java.io.Serializable
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/15
+ */
+class SdkChargeInfo : Serializable {
+
+    var userId: String = ""
+    var roleId: String = ""
+    var roleName: String = ""
+    var roleLevel: String = ""
+    var serverId: String = ""
+    var serverName: String = ""
+    var amount = 0
+    var productId: String = ""
+    var productName: String = ""
+    var productDesc: String = ""
+    var cpOrderId: String = ""
+    var orderId: String = ""
+    var cpCallbackInfo: String = ""
+
+    override fun toString(): String {
+        return "SdkChargeInfo(userId='$userId', roleId='$roleId', roleName='$roleName', roleLevel='$roleLevel', serverId='$serverId', serverName='$serverName', amount=$amount, productId='$productId', productName='$productName', productDesc='$productDesc', cpOrderId='$cpOrderId', orderId='$orderId', cpCallbackInfo='$cpCallbackInfo')"
+    }
+
+}

+ 23 - 0
library_base/src/main/java/cn/yyxx/columbus/base/entity/SdkRoleInfo.kt

@@ -0,0 +1,23 @@
+package cn.yyxx.columbus.base.entity
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/15
+ */
+class SdkRoleInfo {
+
+    var userId: String = ""
+    var roleId: String = ""
+    var roleName: String = ""
+    var roleLevel: String = ""
+    var serverId: String = ""
+    var serverName: String = ""
+    var vipLevel: String = ""
+    var balance: String = ""
+
+
+    override fun toString(): String {
+        return "SdkRoleInfo(userId='$userId', roleId='$roleId', roleName='$roleName', roleLevel='$roleLevel', serverId='$serverId', serverName='$serverName', vipLevel='$vipLevel', balance='$balance')"
+    }
+
+}

+ 10 - 0
library_base/src/main/java/cn/yyxx/columbus/base/internal/IInitialize.kt

@@ -0,0 +1,10 @@
+package cn.yyxx.columbus.base.internal
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/16
+ */
+interface IInitialize {
+
+    fun onResult(code: Int, msg: String)
+}

+ 68 - 0
library_base/src/main/java/cn/yyxx/columbus/base/utils/ParamsUtils.kt

@@ -0,0 +1,68 @@
+package cn.yyxx.columbus.base.utils
+
+import android.content.Context
+import android.text.TextUtils
+import cn.yyxx.support.PropertiesUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+object ParamsUtils {
+
+    private const val CONFIG_FILE = "yyxx_cfg.properties"
+    private const val YYXX_GCP_CODE = "YYXX_GCP_CODE"
+    private const val YYXX_GAME_CODE = "YYXX_GAME_CODE"
+    private const val YYXX_GOOGLE_APP_ID = "YYXX_GOOGLE_APP_ID"
+    private const val YYXX_GOOGLE_CLIENT_ID = "YYXX_GOOGLE_CLIENT_ID"
+
+    fun getGcpCode(context: Context): String {
+        try {
+            val code = PropertiesUtils.getValue4Properties(context, CONFIG_FILE, "yyxx_game", YYXX_GCP_CODE)
+            if (!TextUtils.isEmpty(code)) {
+                return code
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        return ""
+    }
+
+    fun getGameCode(context: Context): String {
+        try {
+            val code = PropertiesUtils.getValue4Properties(context, CONFIG_FILE, "yyxx_game", YYXX_GAME_CODE)
+            if (!TextUtils.isEmpty(code)) {
+                return code
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        return ""
+    }
+
+
+    fun getGoogleAppId(context: Context): String {
+        try {
+            val appId = PropertiesUtils.getValue4Properties(context, CONFIG_FILE, "yyxx_game", YYXX_GOOGLE_APP_ID)
+            if (!TextUtils.isEmpty(appId)) {
+                return appId
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        return ""
+    }
+
+    fun getGoogleClientId(context: Context): String {
+        try {
+            val clientId = PropertiesUtils.getValue4Properties(context, CONFIG_FILE, "yyxx_game", YYXX_GOOGLE_CLIENT_ID)
+            if (!TextUtils.isEmpty(clientId)) {
+                return clientId
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        return ""
+    }
+
+}

+ 1 - 1
library_core/CMakeLists.txt

@@ -11,7 +11,6 @@ cmake_minimum_required(VERSION 3.4.1)
 # Gradle automatically packages shared libraries with your APK.
 
 
-
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/include)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/include/third_part)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/include/aes)
@@ -29,6 +28,7 @@ add_library(local_openssl STATIC IMPORTED)
 set_target_properties(local_crypto PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/libs/${ANDROID_ABI}/libcrypto.a)
 set_target_properties(local_openssl PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/libs/${ANDROID_ABI}/libssl.a)
 
+
 add_library(
         columbus
         SHARED

+ 18 - 2
library_core/build.gradle

@@ -9,13 +9,13 @@ android {
     buildToolsVersion BUILD_TOOLS_VERSION
 
     defaultConfig {
-        minSdkVersion 21
+        minSdkVersion MIN_SDK_VERSION
         targetSdkVersion TARGET_SDK_VERSION
 
         externalNativeBuild {
             cmake {
                 cppFlags '-std=c++11 -frtti -fexceptions -lz'
-                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
+//                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
             }
         }
 
@@ -60,8 +60,24 @@ android {
             path "CMakeLists.txt"
         }
     }
+
+    ndkVersion NDK_VERSION
 }
 
 dependencies {
+    implementation 'androidx.core:core-ktx:1.3.2'
+    implementation 'androidx.fragment:fragment-ktx:1.3.2'
+    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+    implementation 'com.google.android.material:material:1.3.0'
+
+    implementation 'com.google.android.play:core:1.10.0'
+    implementation 'com.google.android.gms:play-services-auth:19.0.0'
+    implementation 'com.android.billingclient:billing-ktx:3.0.3'
+
+
+    implementation 'com.facebook.android:facebook-login:9.0.0'
+
     api project(':library_base')
+//    api project(':library_comm')
+
 }

+ 26 - 0
library_core/src/main/AndroidManifest.xml

@@ -2,4 +2,30 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="cn.yyxx.columbus.core">
 
+    <!-- 网络权限 -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="com.android.vending.BILLING" />
+    <uses-permission android:name="com.farsitel.bazaar.permission.PAY_THROUGH_BAZAAR" />
+
+    <application
+        android:allowBackup="true"
+        android:supportsRtl="true"
+        android:usesCleartextTraffic="true">
+
+        <activity
+            android:name=".impl.login.LoginActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+            android:imeOptions="flagNoFullscreen|flagNoExtractUi"
+            android:launchMode="singleTask"
+            android:theme="@style/ColumbusTheme"
+            android:windowSoftInputMode="adjustResize|stateHidden|stateVisible" />
+
+
+    </application>
+
 </manifest>

+ 12 - 13
library_core/src/main/cpp/aes_utils.cpp

@@ -15,30 +15,30 @@ static const unsigned char CHAR_SET[36] = {'0', '1', '2', '3', '4', '5', '6', '7
 
 uint8_t *AesUtils::GetPaddingInput(const char *input) {
     // 输入的长度
-    int inLength = (int) strlen(input);
-    int remainder = inLength % BLOCKLEN;
-    uint8_t *paddingInput = nullptr;
-    int group = inLength / BLOCKLEN;
+    int input_len = (int) strlen(input);
+    int remainder = input_len % BLOCKLEN;
+    uint8_t *padding_input = nullptr;
+    int group = input_len / BLOCKLEN;
     auto size = (size_t) (BLOCKLEN * (group + 1));
 
-    paddingInput = (uint8_t *) malloc(size + 1);
+    padding_input = (uint8_t *) malloc(size + 1);
 
-    int dif = (int) size - inLength;
+    int dif = (int) size - input_len;
     for (int i = 0; i < size; i++) {
-        if (i < inLength) {
-            paddingInput[i] = (uint8_t) input[i];
+        if (i < input_len) {
+            padding_input[i] = (uint8_t) input[i];
         } else {
             if (remainder == 0) {
                 // 刚好是16倍数, 就填充16个16 (0x10)
-                paddingInput[i] = HEX[0];
+                padding_input[i] = HEX[0];
             } else {
                 // 如果不足16位 少多少位就补几个几
-                paddingInput[i] = HEX[dif];
+                padding_input[i] = HEX[dif];
             }
         }
     }
-    paddingInput[size] = '\0';
-    return paddingInput;
+    padding_input[size] = '\0';
+    return padding_input;
 }
 
 int AesUtils::FindPaddingIndex(uint8_t *str, size_t length) {
@@ -109,7 +109,6 @@ char *AesUtils::Encrypt(const char *input) {
  * AES解密, CBC, PKCS5Padding
  */
 char *AesUtils::Decrypt(const char *input, const uint8_t *key) {
-//    const uint8_t *AES_KEY = getKey();
     const uint8_t *iv = GetIv(key);
 
     size_t len = strlen(input);

+ 40 - 0
library_core/src/main/cpp/base64_utils.cpp

@@ -0,0 +1,40 @@
+//
+// Created by #Suyghur, on 2021/06/16.
+//
+
+#include "include/base64_utils.h"
+#include <third_part/openssl/bio.h>
+#include <third_part/openssl/pem.h>
+
+std::string Base64Utils::Encode(const std::string &src) {
+    BIO *bio;
+    BIO *b64;
+    BUF_MEM *buffer_ptr;
+
+    b64 = BIO_new(BIO_f_base64());
+    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+    bio = BIO_new(BIO_s_mem());
+    bio = BIO_push(b64, bio);
+    //encode
+    BIO_write(bio, src.c_str(), (int) src.length());
+    BIO_flush(bio);
+    BIO_get_mem_ptr(bio, &buffer_ptr);
+    std::string raw(buffer_ptr->data, buffer_ptr->length);
+    BIO_free_all(bio);
+    return raw;
+}
+
+char *Base64Utils::Decode(const char *raw) {
+    BIO *b64 = nullptr;
+    BIO *bmem = nullptr;
+    int len = strlen(raw);
+    char *buffer = (char *) malloc(len);
+    memset(buffer, 0, len);
+    b64 = BIO_new(BIO_f_base64());
+    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+    bmem = BIO_new_mem_buf(raw, len);
+    bmem = BIO_push(b64, bmem);
+    BIO_read(bmem, buffer, len);
+    BIO_free_all(bmem);
+    return buffer;
+}

+ 22 - 0
library_core/src/main/cpp/include/base64_utils.h

@@ -0,0 +1,22 @@
+//
+// Created by #Suyghur, on 2021/06/16.
+//
+
+#ifndef COLUMBUS_BASE64_UTILS_H
+#define COLUMBUS_BASE64_UTILS_H
+
+
+#include <string>
+
+class Base64Utils {
+
+public:
+
+    static std::string Encode(const std::string &src);
+
+    static char *Decode(const char *raw);
+
+};
+
+
+#endif //COLUMBUS_BASE64_UTILS_H

+ 3 - 3
library_core/src/main/cpp/include/rsa/rsa_utils.h

@@ -25,9 +25,9 @@ private:
     static std::string Decrypt(const std::string &public_key, const std::string &src);
 
 
-    static std::string Base64Encode(const std::string &src);
-
-    static char *Base64Decode(const char *raw);
+//    static std::string Encode(const std::string &src);
+//
+//    static char *Decode(const char *raw);
 
 
 };

+ 4 - 36
library_core/src/main/cpp/rsa_utils.cpp

@@ -5,6 +5,7 @@
 #include <third_part/openssl/ossl_typ.h>
 #include <third_part/openssl/bio.h>
 #include <third_part/openssl/pem.h>
+#include "include/base64_utils.h"
 #include "include/rsa/rsa_utils.h"
 
 /**
@@ -20,7 +21,7 @@ std::string RsaUtils::EncryptByPublicKey(std::string public_key, std::string src
 
 //    LOGD("raw : %s", raw.c_str());
 
-    std::string base64_raw = Base64Encode(raw);
+    std::string base64_raw = Base64Utils::Encode(raw);
     if (base64_raw.empty()) {
         return nullptr;
     }
@@ -146,11 +147,11 @@ std::string RsaUtils::Decrypt(const std::string &public_key, const std::string &
     //填充0
     memset(src, 0, rsa_size + 1);
     //加密,返回值为加密后的密文长度,-1表示失败
-    auto *data = reinterpret_cast<unsigned char *>(Base64Decode(raw.c_str()));
+    auto *data = reinterpret_cast<unsigned char *>(Base64Utils::Decode(raw.c_str()));
     int len = strlen((char *) data);
     std::string d = (char *) data;
 
-    std::string data_encode = Base64Encode((char *) data);
+    std::string data_encode = Base64Utils::Encode((char *) data);
 
     int status = RSA_public_decrypt(len, data, src, rsa_public_key, RSA_PKCS1_PADDING);
     //解密
@@ -181,38 +182,5 @@ std::string RsaUtils::Decrypt(const std::string &public_key, const std::string &
 
 }
 
-std::string RsaUtils::Base64Encode(const std::string &src) {
-    BIO *bio;
-    BIO *b64;
-    BUF_MEM *buffer_ptr;
-
-    b64 = BIO_new(BIO_f_base64());
-    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-    bio = BIO_new(BIO_s_mem());
-    bio = BIO_push(b64, bio);
-    //encode
-    BIO_write(bio, src.c_str(), (int) src.length());
-    BIO_flush(bio);
-    BIO_get_mem_ptr(bio, &buffer_ptr);
-    std::string raw(buffer_ptr->data, buffer_ptr->length);
-    BIO_free_all(bio);
-    return raw;
-}
-
-char *RsaUtils::Base64Decode(const char *raw) {
-    BIO *b64 = nullptr;
-    BIO *bmem = nullptr;
-    int len = strlen(raw);
-    char *buffer = (char *) malloc(len);
-    memset(buffer, 0, len);
-    b64 = BIO_new(BIO_f_base64());
-    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-    bmem = BIO_new_mem_buf(raw, len);
-    bmem = BIO_push(b64, bmem);
-    BIO_read(bmem, buffer, len);
-    BIO_free_all(bmem);
-    return buffer;
-}
-
 
 

+ 22 - 6
library_core/src/main/cpp/columbus.cpp → library_core/src/main/cpp/sdk_drive.cpp

@@ -69,13 +69,29 @@ static jstring RsaDecrypt(JNIEnv *env, jobject thiz, jstring raw) {
     return result;
 }
 
+static void InitSdkDrive(JNIEnv *env, jobject thiz, jobject context) {
+
+}
+
+static void SetParam(JNIEnv *env, jobject thiz, jstring key, jstring value) {
+
+}
+
+static jstring GetParam(JNIEnv *env, jobject thiz, jstring key) {
+    return nullptr;
+}
+
 
 static JNINativeMethod gMethod[] = {
-        {"getAesKey",  "()V",                                                      (void *) GetAesKey},
-        {"aesEncrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) AesEncrypt},
-        {"aesDecrypt", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) AesDecrypt},
-        {"rsaEncrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) RsaEncrypt},
-        {"rsaDecrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) RsaDecrypt}
+        {"initSdkDrive", "(Landroid/content/Context;)V",            (void *) InitSdkDrive},
+        {"setParam",     "(Ljava/lang/String;Ljava/lang/String;)V", (void *) SetParam},
+        {"getParam",     "(Ljava/lang/String;)Ljava/lang/String;",  (void *) GetParam},
+
+//        {"getAesKey",  "()V",                                                      (void *) GetAesKey},
+//        {"aesEncrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) AesEncrypt},
+//        {"aesDecrypt", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) AesDecrypt},
+//        {"rsaEncrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) RsaEncrypt},
+//        {"rsaDecrypt", "(Ljava/lang/String;)Ljava/lang/String;",                   (void *) RsaDecrypt}
 };
 
 extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -83,7 +99,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
     if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
         return JNI_ERR;
     }
-    jclass clz = env->FindClass("cn/yyxx/columbus/core/SdkDrive");
+    jclass clz = env->FindClass("cn/yyxx/columbus/core/impl/SdkDrive");
     if (env->RegisterNatives(clz, gMethod, sizeof(gMethod) / sizeof(gMethod[0])) < 0) {
         return JNI_ERR;
     }

+ 0 - 11
library_core/src/main/java/cn/yyxx/columbus/Version.kt

@@ -1,11 +0,0 @@
-package cn.yyxx.columbus
-
-/**
- * @author #Suyghur.
- * Created on 2021/06/09
- */
-object Version {
-    const val CORE_VERSION_NAME = "1.0.0"
-    const val CORE_VERSION_CODE = 100
-    const val SERVER_VERSION_NAME = "1.0.0"
-}

+ 101 - 1
library_core/src/main/java/cn/yyxx/columbus/core/SdkBridge.kt

@@ -1,8 +1,108 @@
 package cn.yyxx.columbus.core
 
+import android.app.Activity
+import android.app.Application
+import android.content.Context
+import android.content.Intent
+import cn.yyxx.columbus.base.entity.SdkChargeInfo
+import cn.yyxx.columbus.base.entity.SdkRoleInfo
+import cn.yyxx.columbus.base.internal.ICallback
+import cn.yyxx.columbus.base.internal.IInitialize
+import cn.yyxx.columbus.core.impl.SdkBridgeImpl
+
 /**
  * @author #Suyghur.
  * Created on 2021/06/09
  */
-class SdkBridge {
+class SdkBridge constructor(context: Context) {
+
+    private var mImpl: SdkBridgeImpl? = null
+
+    init {
+        if (mImpl == null) {
+            mImpl = SdkBridgeImpl(context)
+        }
+    }
+
+    fun attachBaseContext(application: Application, context: Context) {
+        mImpl?.attachBaseContext(application, context)
+
+    }
+
+    fun initApplication(application: Application) {
+        mImpl?.initApplication(application)
+    }
+
+    fun initialize(activity: Activity, isLandscape: Boolean, callback: ICallback, initCallback: IInitialize) {
+        mImpl?.initialize(activity, isLandscape, callback, initCallback)
+    }
+
+    fun login(activity: Activity, isAutoLogin: Boolean, callback: ICallback) {
+        mImpl?.login(activity, isAutoLogin, callback)
+    }
+
+    fun logout(activity: Activity, callback: ICallback) {
+        mImpl?.logout(activity, callback)
+    }
+
+    fun charge(activity: Activity, chargeInfo: SdkChargeInfo, callback: ICallback) {
+        mImpl?.charge(activity, chargeInfo, callback)
+    }
+
+    fun roleCreate(activity: Activity, roleInfo: SdkRoleInfo) {
+        mImpl?.roleCreate(activity, roleInfo)
+    }
+
+    fun roleLauncher(activity: Activity, roleInfo: SdkRoleInfo) {
+        mImpl?.roleLauncher(activity, roleInfo)
+    }
+
+    fun roleLevelUp(activity: Activity, roleInfo: SdkRoleInfo) {
+        mImpl?.roleLevelUp(activity, roleInfo)
+    }
+
+    fun openExitView(activity: Activity, callback: ICallback) {
+        mImpl?.openExitView(activity, callback)
+    }
+
+    fun onStart(activity: Activity) {
+        mImpl?.onStart(activity)
+    }
+
+    fun onRestart(activity: Activity) {
+        mImpl?.onRestart(activity)
+    }
+
+    fun onResume(activity: Activity) {
+        mImpl?.onResume(activity)
+    }
+
+    fun onPause(activity: Activity) {
+        mImpl?.onPause(activity)
+    }
+
+    fun onStop(activity: Activity) {
+        mImpl?.onStop(activity)
+    }
+
+    fun onDestroy(activity: Activity) {
+        mImpl?.onDestroy(activity)
+    }
+
+    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, intent: Intent) {
+        mImpl?.onActivityResult(activity, requestCode, resultCode, intent)
+    }
+
+    fun onNewIntent(activity: Activity, intent: Intent) {
+        mImpl?.onNewIntent(activity, intent)
+    }
+
+    fun getCurrentUserId(): String {
+        return if (mImpl == null) {
+            ""
+        } else {
+            mImpl!!.getCurrentUserId()
+        }
+    }
+
 }

+ 0 - 22
library_core/src/main/java/cn/yyxx/columbus/core/SdkDrive.kt

@@ -1,22 +0,0 @@
-package cn.yyxx.columbus.core
-
-/**
- * @author #Suyghur.
- * Created on 2021/06/09
- */
-object SdkDrive {
-
-    init {
-        System.loadLibrary("columbus")
-    }
-
-    external fun getAesKey()
-
-    external fun aesEncrypt(src: String): String
-
-    external fun aesDecrypt(raw: String, key: String): String
-
-    external fun rsaEncrypt(src: String): String
-
-    external fun rsaDecrypt(raw: String): String
-}

+ 24 - 0
library_core/src/main/java/cn/yyxx/columbus/core/entity/ClickType.kt

@@ -0,0 +1,24 @@
+package cn.yyxx.columbus.core.entity
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/19
+ */
+object ClickType {
+
+    //1000
+    const val ACTION_RETURN = 1000
+    const val ACTION_CLOSE = 1001
+    const val ACTION_LAUNCHER = 1002
+    const val ACTION_REGISTER = 1003
+    const val ACTION_FORGET = 1004
+    const val ACTION_GOOGLE_MODE = 1005
+    const val ACTION_FACEBOOK_MODE = 1006
+    const val ACTION_ACCOUNT_MODE = 1007
+    const val ACTION_GUEST_MODE = 1008
+    const val ACTION_CLICK_CHECK = 1009
+    const val ACTION_CLICK_AGREEMENT = 1010
+    const val ACTION_CONFIRM = 1011
+    const val ACTION_MORE_ACCOUNT = 1012
+    const val ACTION_CLICK_EYE = 1013
+}

+ 14 - 0
library_core/src/main/java/cn/yyxx/columbus/core/entity/LoginType.kt

@@ -0,0 +1,14 @@
+package cn.yyxx.columbus.core.entity
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/19
+ */
+object LoginType {
+
+    const val TYPE_GUEST_LOGIN = 0
+    const val TYPE_FACEBOOK_LOGIN = 1
+    const val TYPE_APPLE_LOGIN = 2
+    const val TYPE_GOOGLE_LOGIN = 3
+    const val TYPE_ACCOUNT_LOGIN = 4
+}

+ 50 - 0
library_core/src/main/java/cn/yyxx/columbus/core/entity/SdkBackLoginInfo.kt

@@ -0,0 +1,50 @@
+package cn.yyxx.columbus.core.entity
+
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class SdkBackLoginInfo private constructor() {
+
+    var userId = ""
+    var token = ""
+    var isRegUser = false
+    var hasBindPhone = false
+    var hasBindAccount = false
+    var loginType = -1
+
+
+    fun reset() {
+        this.userId = ""
+        this.token = ""
+        this.isRegUser = false
+        this.hasBindPhone = false
+        this.hasBindAccount = false
+        this.loginType = -1
+    }
+
+    fun toJsonString(): String {
+        val jsonObject = JSONObject()
+        try {
+            jsonObject.put("user_id", userId)
+            jsonObject.put("token", token)
+        } catch (e: JSONException) {
+            e.printStackTrace()
+        }
+        return jsonObject.toString()
+    }
+
+    override fun toString(): String {
+        return "SdkBackLoginInfo(userId='$userId', token='$token', isRegUser=$isRegUser, hasBindPhone=$hasBindPhone, hasBindAccount=$hasBindAccount, loginType=$loginType)"
+    }
+
+
+    companion object {
+        val instance: SdkBackLoginInfo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
+            SdkBackLoginInfo()
+        }
+    }
+}

+ 97 - 0
library_core/src/main/java/cn/yyxx/columbus/core/entity/bean/init/FloatCfg.kt

@@ -0,0 +1,97 @@
+package cn.yyxx.columbus.core.entity.bean.init
+
+import cn.yyxx.support.JsonUtils
+import org.json.JSONObject
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/19
+ */
+class FloatCfg {
+
+    var switch = 0
+    var floatIconUrl = ""
+    lateinit var memberCfg: FeatureCfg
+    lateinit var gifCfg: FeatureCfg
+    lateinit var gmCfg: FeatureCfg
+    lateinit var chargeCfg: FeatureCfg
+    lateinit var inviteCfg: FeatureCfg
+
+    override fun toString(): String {
+        return "FloatCfg(switch=$switch, floatIconUrl='$floatIconUrl', memberCfg=$memberCfg, gifCfg=$gifCfg, gmCfg=$gmCfg, chargeCfg=$chargeCfg, inviteCfg=$inviteCfg)"
+    }
+
+    companion object {
+
+        fun toBean(floatCfg: JSONObject): FloatCfg {
+            val bean = FloatCfg()
+            bean.memberCfg = FeatureCfg()
+            bean.gifCfg = FeatureCfg()
+            bean.gmCfg = FeatureCfg()
+            bean.chargeCfg = FeatureCfg()
+            bean.inviteCfg = FeatureCfg()
+            if (JsonUtils.hasJsonKey(floatCfg, "switch")) {
+                bean.switch = floatCfg.getInt("switch")
+            }
+
+            if (JsonUtils.hasJsonKey(floatCfg, "float_icon_url")) {
+                bean.floatIconUrl = floatCfg.getString("float_icon_url")
+            }
+
+            if (JsonUtils.hasJsonKey(floatCfg, "feature_cfg")) {
+                val featureCfg = floatCfg.getJSONObject("feature_cfg")
+                if (JsonUtils.hasJsonKey(featureCfg, "member_cfg")) {
+                    bean.memberCfg = FeatureCfg.toBean(featureCfg.getJSONObject("member_cfg"))
+                }
+
+                if (JsonUtils.hasJsonKey(featureCfg, "gif_cfg")) {
+                    bean.gifCfg = FeatureCfg.toBean(featureCfg.getJSONObject("gif_cfg"))
+                }
+
+                if (JsonUtils.hasJsonKey(featureCfg, "gm_cfg")) {
+                    bean.gmCfg = FeatureCfg.toBean(featureCfg.getJSONObject("gm_cfg"))
+                }
+
+                if (JsonUtils.hasJsonKey(featureCfg, "charge_cfg")) {
+                    bean.chargeCfg = FeatureCfg.toBean(featureCfg.getJSONObject("charge_cfg"))
+                }
+
+                if (JsonUtils.hasJsonKey(featureCfg, "invite_cfg")) {
+                    bean.inviteCfg = FeatureCfg.toBean(featureCfg.getJSONObject("invite_cfg"))
+                }
+            }
+            return bean
+        }
+    }
+
+
+    class FeatureCfg {
+        var switch = 0
+        var iconUrl = ""
+        var url = ""
+
+        override fun toString(): String {
+            return "FeatureCfg(switch=$switch, iconUrl='$iconUrl', url='$url')"
+        }
+
+        companion object {
+            fun toBean(cfg: JSONObject): FeatureCfg {
+                val bean = FeatureCfg()
+                if (JsonUtils.hasJsonKey(cfg, "switch")) {
+                    bean.switch = cfg.getInt("switch")
+                }
+
+                if (JsonUtils.hasJsonKey(cfg, "icon_url")) {
+                    bean.iconUrl = cfg.getString("icon_url")
+                }
+
+                if (JsonUtils.hasJsonKey(cfg, "url")) {
+                    bean.url = cfg.getString("url")
+                }
+                return bean
+            }
+        }
+
+    }
+
+}

+ 102 - 0
library_core/src/main/java/cn/yyxx/columbus/core/entity/bean/init/InitBean.kt

@@ -0,0 +1,102 @@
+package cn.yyxx.columbus.core.entity.bean.init
+
+import android.text.TextUtils
+import cn.yyxx.support.JsonUtils
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/19
+ */
+class InitBean private constructor() {
+
+    lateinit var noticeCfg: NoticeCfg
+    lateinit var privacyCfg: PrivacyCfg
+    lateinit var floatCfg: FloatCfg
+
+    var rewardId = ""
+
+    override fun toString(): String {
+        return "InitBean(noticeCfg=$noticeCfg, privacyCfg=$privacyCfg, floatCfg=$floatCfg, rewardId='$rewardId')"
+    }
+
+    companion object {
+        fun toBean(json: String): InitBean {
+            val bean = InitBean()
+            bean.noticeCfg = NoticeCfg()
+            bean.privacyCfg = PrivacyCfg()
+            bean.floatCfg = FloatCfg()
+
+            if (TextUtils.isEmpty(json)) {
+                return bean
+            }
+
+            try {
+                val jsonObject = JSONObject(json)
+
+                if (JsonUtils.hasJsonKey(jsonObject, "notice_cfg")) {
+                    val cfg = jsonObject.getJSONObject("notice_cfg")
+                    if (JsonUtils.hasJsonKey(cfg, "switch")) {
+                        bean.noticeCfg.switch = cfg.getInt("switch")
+                    }
+
+                    if (JsonUtils.hasJsonKey(cfg, "url")) {
+                        bean.noticeCfg.url = cfg.getString("url")
+                    }
+
+                    if (JsonUtils.hasJsonKey(cfg, "show_count")) {
+                        bean.noticeCfg.showCount = cfg.getInt("show_count")
+                    }
+                }
+
+                if (JsonUtils.hasJsonKey(jsonObject, "privacy_cfg")) {
+                    val cfg = jsonObject.getJSONObject("privacy_cfg")
+                    if (JsonUtils.hasJsonKey(cfg, "switch")) {
+                        bean.privacyCfg.switch = cfg.getInt("switch")
+                    }
+
+                    if (JsonUtils.hasJsonKey(cfg, "url")) {
+                        bean.privacyCfg.url = cfg.getString("url")
+                    }
+                }
+
+                if (JsonUtils.hasJsonKey(jsonObject, "float_cfg")) {
+                    val cfg = jsonObject.getJSONObject("float_cfg")
+                    bean.floatCfg = FloatCfg.toBean(cfg)
+                }
+
+                if (JsonUtils.hasJsonKey(jsonObject, "reward_id")) {
+                    bean.rewardId = jsonObject.getString("reward_id")
+                }
+            } catch (e: JSONException) {
+                e.printStackTrace()
+            }
+            return bean
+        }
+
+    }
+
+    class NoticeCfg {
+
+        var switch = 0
+        var url = ""
+        var showCount = 0
+
+        override fun toString(): String {
+            return "NoticeCfg(switch=$switch, url='$url', showCount=$showCount)"
+        }
+
+    }
+
+    class PrivacyCfg {
+        var switch = 0
+        var url = ""
+
+        override fun toString(): String {
+            return "PrivacyCfg(switch=$switch, url='$url')"
+        }
+
+    }
+
+}

+ 180 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/SdkBridgeImpl.kt

@@ -0,0 +1,180 @@
+package cn.yyxx.columbus.core.impl
+
+import android.app.Activity
+import android.app.Application
+import android.content.Context
+import android.content.Intent
+import android.text.TextUtils
+import cn.yyxx.columbus.base.entity.SdkChargeInfo
+import cn.yyxx.columbus.base.entity.SdkRoleInfo
+import cn.yyxx.columbus.base.internal.ICallback
+import cn.yyxx.columbus.base.internal.IInitialize
+import cn.yyxx.columbus.base.utils.Logger
+import cn.yyxx.columbus.core.entity.SdkBackLoginInfo
+import cn.yyxx.columbus.core.entity.bean.init.InitBean
+import cn.yyxx.columbus.core.impl.login.LoginActivity
+import cn.yyxx.columbus.core.internal.IImplCallback
+import cn.yyxx.columbus.core.network.Host
+import cn.yyxx.support.device.DeviceInfoUtils
+import cn.yyxx.support.gaid.GAIDUtils
+import cn.yyxx.support.hawkeye.LogUtils
+import cn.yyxx.support.hawkeye.OwnDebugUtils
+import cn.yyxx.support.hawkeye.ToastUtils
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/16
+ */
+class SdkBridgeImpl(context: Context) {
+
+
+    private var hasReadGaid = false
+
+    @Volatile
+    private var timeCount = AtomicInteger(0)
+
+    init {
+        Host.initHostModel(context)
+        LogUtils.DEBUG = OwnDebugUtils.isOwnDebug(context, "yyxx_cfg.properties", "yyxx_game", "YYXX_OWN_DEBUG")
+    }
+
+    fun attachBaseContext(application: Application, context: Context) {
+        Logger.initZap(application)
+        Logger.i("Columbus attachBaseContext ...")
+        GAIDUtils.initGoogleAdid(application) { code, _ ->
+            if (code == 0) {
+                Logger.i("谷歌框架可以访问,请求gaid")
+                Logger.i("gaid : ${GAIDUtils.getGoogleAdid()}")
+            } else {
+                Logger.e("谷歌框架不可访问,使用android id替代")
+                Logger.e("android id : ${DeviceInfoUtils.getAndroidDeviceId(application)}")
+            }
+            hasReadGaid = true
+        }
+    }
+
+    fun initApplication(application: Application) {
+        Logger.i("Columbus initApplication ...")
+        SdkDrive.getInstance().initSdkDrive(application)
+    }
+
+    fun initialize(activity: Activity, isLandscape: Boolean, callback: ICallback, initCallback: IInitialize) {
+        Logger.i("Columbus initialize ...")
+
+        if (!hasReadGaid) {
+            Logger.e("还未完成gaid加载,将延迟初始化")
+            //TODO showInitDialog
+            Thread {
+                while (!hasReadGaid) {
+                    try {
+                        Logger.e("还未完成gaid加载,延迟1s初始化,$hasReadGaid")
+                        Thread.sleep(1000)
+                        timeCount.getAndIncrement()
+                    } catch (e: InterruptedException) {
+                        e.printStackTrace()
+                    }
+                }
+                activity.runOnUiThread {
+                    if (TextUtils.isEmpty(GAIDUtils.getGoogleAdid())) {
+                        Logger.e("加载gaid失败,共延迟${timeCount}s初始化,将进行初始化操作...")
+                    } else {
+                        Logger.i("加载gaid成功,共延迟${timeCount}s初始化,将进行初始化操作...")
+                    }
+                    //TODO hideInitDialog
+                    startSdkInit(activity, callback, initCallback)
+                }
+            }
+        } else {
+            Logger.i("加载gaid成功,开始初始化...")
+            startSdkInit(activity, callback, initCallback)
+        }
+    }
+
+    private fun startSdkInit(activity: Activity, callback: ICallback, initCallback: IInitialize) {
+        val test =
+            "{\"notice_cfg\":{\"switch\":1,\"url\":\"https://www.baidu.com\",\"show_count\":1},\"privacy_cfg\":{\"switch\":1,\"url\":\"https://www.baidu.com\"},\"float_cfg\":{\"switch\":1,\"float_icon_url\":\"https://www.baidu.com\",\"feature_cfg\":{\"member_cfg\":{\"switch\":1,\"icon_url\":\"https://www.baidu.com\",\"url\":\"https://www.baidu.com\"},\"gif_cfg\":{\"switch\":1,\"icon_url\":\"https://www.baidu.com\",\"url\":\"https://www.baidu.com\"},\"gm_cfg\":{\"switch\":1,\"icon_url\":\"https://www.baidu.com\",\"url\":\"https://www.baidu.com\"},\"charge_cfg\":{\"switch\":1,\"icon_url\":\"https://www.baidu.com\",\"url\":\"https://www.baidu.com\"},\"invite_cfg\":{\"switch\":1,\"icon_url\":\"https://www.baidu.com\",\"url\":\"https://www.baidu.com\"}}},\"reward_id\":\"com.yyxx.yzcjl60\",\"area_code_list\":[\"86\",\"886\",\"862\"]}"
+        initBean = InitBean.toBean(test)
+        Logger.d(initBean)
+        callback.onResult(0, "")
+        initCallback.onResult(0, "")
+    }
+
+    fun login(activity: Activity, isAutoLogin: Boolean, callback: ICallback) {
+        LoginActivity.login(activity, isAutoLogin, object : IImplCallback {
+            override fun onResult(code: Int, result: String) {
+                Logger.d("onResult code : $code , result : $result")
+                ToastUtils.toastInfo(activity, "onResult code : $code , result : $result")
+            }
+        })
+    }
+
+    fun logout(activity: Activity, callback: ICallback) {
+
+    }
+
+    fun charge(activity: Activity, chargeInfo: SdkChargeInfo, callback: ICallback) {
+
+    }
+
+    fun roleCreate(activity: Activity, roleInfo: SdkRoleInfo) {
+
+    }
+
+    fun roleLauncher(activity: Activity, roleInfo: SdkRoleInfo) {
+
+    }
+
+    fun roleLevelUp(activity: Activity, roleInfo: SdkRoleInfo) {
+
+    }
+
+    fun openExitView(activity: Activity, callback: ICallback) {
+
+    }
+
+    fun onStart(activity: Activity) {
+
+    }
+
+    fun onRestart(activity: Activity) {
+
+    }
+
+    fun onResume(activity: Activity) {
+
+    }
+
+    fun onPause(activity: Activity) {
+
+    }
+
+    fun onStop(activity: Activity) {
+
+    }
+
+    fun onDestroy(activity: Activity) {
+
+    }
+
+    fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, intent: Intent) {
+
+    }
+
+    fun onNewIntent(activity: Activity, intent: Intent) {
+
+    }
+
+    fun getCurrentUserId(): String {
+        return SdkBackLoginInfo.instance.userId
+    }
+
+    companion object {
+
+        var isLand = false
+
+        lateinit var initBean: InitBean
+
+    }
+
+}

+ 50 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/SdkDrive.kt

@@ -0,0 +1,50 @@
+package cn.yyxx.columbus.core.impl
+
+import android.content.Context
+import androidx.annotation.Keep
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/09
+ */
+class SdkDrive private constructor() {
+
+    init {
+        System.loadLibrary("columbus")
+    }
+
+//    external fun getAesKey()
+//
+//    external fun aesEncrypt(src: String): String
+//
+//    external fun aesDecrypt(raw: String, key: String): String
+//
+//    external fun rsaEncrypt(src: String): String
+//
+//    external fun rsaDecrypt(raw: String): String
+
+    external fun initSdkDrive(context: Context)
+
+    external fun setParam(key: String, value: String)
+
+    external fun getParam(key: String): String
+
+    companion object {
+        @JvmStatic
+        @Keep
+        fun getInstance(): SdkDrive {
+            return SdkDriveHolder.INSTANCE
+        }
+
+        private object SdkDriveHolder {
+            val INSTANCE: SdkDrive = SdkDrive()
+        }
+
+        /**
+         * 防止单例对象在反序列化时重新生成对象
+         */
+        private fun readResolve(): Any {
+            return SdkDriveHolder.INSTANCE
+        }
+    }
+}

+ 90 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/iab/InAppBilling.kt

@@ -0,0 +1,90 @@
+package cn.yyxx.columbus.core.impl.iab
+
+import android.app.Activity
+import android.content.Context
+import cn.yyxx.columbus.base.utils.Logger
+import com.android.billingclient.api.BillingClient
+import com.android.billingclient.api.BillingClientStateListener
+import com.android.billingclient.api.BillingResult
+import com.android.billingclient.api.Purchase
+import com.google.android.gms.common.ConnectionResult
+import com.google.android.gms.common.GoogleApiAvailability
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+abstract class InAppBilling {
+
+    protected var billingClient: BillingClient? = null
+
+    protected fun checkGoogleApiAvailability(context: Context): Boolean {
+        return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
+    }
+
+    protected fun initializeBillingClient(context: Context) {
+
+    }
+
+    /**
+     * charge
+     * Purchase{"orderId":"GPA.3325-4558-9050-03633","packageName":"com.flyfun.demo","productId":"com.flyfun.ylj.60","purchaseTime":1618367632652,"purchaseState":4,"purchaseToken":"mpfdmeeoemplddgfknnkgnlf.AO-J1Owpfua8OfxpU_sjOBTY_ZgRoN3Km-mNJdmie9Qpd1w-DDQjtkUfcWOGhScHHeJ9ogWqkP_01w5WHp9Pfnpvgx1_nffDYA","acknowledged":false}
+     */
+    protected abstract fun chargePurchasesUpdated(activity: Activity, purchase: Purchase)
+
+    /**
+     * pre reward
+     * Purchase{"packageName":"com.flyfun.demo","productId":"com.flyfun.demo70","purchaseTime":1618367980837,"purchaseState":0,"purchaseToken":"cdphbkooagehckdcmkhmbhmd.AO-J1OzHTtCRDhd8k1Qfp3FU0GgYQUSaCx6I6W6Oi_P2tiS3LWKIdb6jTkc-tTqfcCagPxw2nPqujl9s10KuCunTl3OLSiIN9A"}
+     */
+    protected abstract fun preRewardPurchasesUpdated(activity: Activity, purchase: Purchase)
+
+    protected abstract fun queryRewardInfo(activity: Activity)
+
+    protected abstract fun queryChargeInfo(activity: Activity)
+
+    protected abstract fun purchasesUpdatedFailed()
+
+    protected abstract fun connectGooglePlayFailed()
+
+    protected fun connectGooglePlay(activity: Activity, isPreReward: Boolean = false) {
+        billingClient?.apply {
+            if (!isReady) {
+                Logger.d("start connection Google Play ...")
+                startConnection(object : BillingClientStateListener {
+                    override fun onBillingSetupFinished(billingResult: BillingResult) {
+                        logBillingResult("onBillingSetupFinished", billingResult)
+                        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
+                            if (isPreReward) {
+                                queryRewardInfo(activity)
+                            } else {
+                                queryChargeInfo(activity)
+                            }
+                        } else {
+                            connectGooglePlayFailed()
+                        }
+                    }
+
+                    override fun onBillingServiceDisconnected() {
+                        Logger.e("onBillingServiceDisconnected")
+                        connectGooglePlay(activity, isPreReward)
+                    }
+                })
+            }
+        }
+    }
+
+    protected fun disConnection() {
+        billingClient?.apply {
+            if (isReady) {
+                Logger.d("断开谷歌收银台连接,以清空被消耗或者失败的缓存订单")
+                endConnection()
+            }
+        }
+    }
+
+    protected fun logBillingResult(callbackFuncName: String, billingResult: BillingResult) {
+        val code = billingResult.responseCode
+        val msg = billingResult.debugMessage
+        Logger.d("$callbackFuncName , code : $code , msg : $msg")
+    }
+}

+ 287 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/login/LoginActivity.kt

@@ -0,0 +1,287 @@
+package cn.yyxx.columbus.core.impl.login
+
+import android.app.Activity
+import android.content.DialogInterface
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.view.*
+import android.view.inputmethod.InputMethodManager
+import android.widget.EditText
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.content.ContextCompat
+import androidx.core.view.ViewCompat
+import androidx.fragment.app.FragmentActivity
+import cn.yyxx.columbus.core.entity.ClickType
+import cn.yyxx.columbus.core.impl.SdkBridgeImpl
+import cn.yyxx.columbus.core.impl.login.fragment.LauncherFragment
+import cn.yyxx.columbus.core.internal.IImplCallback
+import cn.yyxx.columbus.core.ui.NoScrollViewPager
+import cn.yyxx.columbus.core.ui.dialog.ChooseLoginDialog
+import cn.yyxx.support.AndroidBug5497Workaround
+import cn.yyxx.support.DensityUtils
+import cn.yyxx.support.ResUtils
+import com.google.android.material.tabs.TabLayout
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class LoginActivity : FragmentActivity(), View.OnClickListener {
+
+    lateinit var userSignInImpl: UserSignInImpl
+        private set
+
+    private lateinit var rootContainer: ConstraintLayout
+    private lateinit var loginContainer: ConstraintLayout
+    private lateinit var tabLayout: TabLayout
+    private lateinit var viewPager: NoScrollViewPager
+
+    private var chooseDialog: ChooseLoginDialog? = null
+
+    private var leftSelect = 0
+    private var leftSelected = 0
+    private var rightSelect = 0
+    private var rightSelected = 0
+
+    private var showFragment = false
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        userSignInImpl = UserSignInImpl(this, object : UserSignInImpl.ISignInCallback {
+            override fun onSuccess(result: String) {
+                hideChooseDialog()
+                this@LoginActivity.finish()
+                implCallback?.onResult(0, result)
+            }
+
+            override fun onFailed(result: String) {
+                implCallback?.onResult(-1, result)
+            }
+
+        })
+        initChooseDialog()
+        initView()
+    }
+
+    private fun initChooseDialog() {
+        if (chooseDialog != null) {
+            chooseDialog?.dismiss()
+            chooseDialog = null
+        }
+        chooseDialog = ChooseLoginDialog(this)
+
+        chooseDialog?.apply {
+            typeGoogle.tag = ClickType.ACTION_GOOGLE_MODE
+            typeGoogle.setOnClickListener(this@LoginActivity)
+
+            typeFacebook.tag = ClickType.ACTION_FACEBOOK_MODE
+            typeFacebook.setOnClickListener(this@LoginActivity)
+
+            typeAccount.tag = ClickType.ACTION_ACCOUNT_MODE
+            typeAccount.setOnClickListener(this@LoginActivity)
+
+            typeGuest.tag = ClickType.ACTION_GUEST_MODE
+            typeGuest.setOnClickListener(this@LoginActivity)
+
+            setOnKeyListener(object : DialogInterface.OnKeyListener {
+                override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent?): Boolean {
+                    if (keyCode == KeyEvent.KEYCODE_BACK) {
+                        hideChooseDialog()
+                        this@LoginActivity.finish()
+                        return true
+                    }
+                    return false
+                }
+
+            })
+            show()
+        }
+
+    }
+
+    private fun initView() {
+        if (SdkBridgeImpl.isLand) {
+            window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
+        }
+        setContentView(ResUtils.getResId(this, "yyxx_login", "layout"))
+
+        if (!SdkBridgeImpl.isLand) {
+            AndroidBug5497Workaround.assistActivity(this)
+        }
+
+        rootContainer = findViewById(ResUtils.getResId(this, "yyxx_login_container", "id"))
+
+        loginContainer = findViewById(ResUtils.getResId(this, "yyxx_cl_login", "id"))
+        loginContainer.visibility = View.VISIBLE
+
+        tabLayout = findViewById(ResUtils.getResId(this, "yyxx_tl", "id"))
+        //横屏下反射修改TabLayout的requestedTabMinWidth
+        if (SdkBridgeImpl.isLand) {
+            val requestedTabMinWidth = TabLayout::class.java.getDeclaredField("requestedTabMinWidth")
+            requestedTabMinWidth.isAccessible = true
+            requestedTabMinWidth.set(tabLayout, DensityUtils.dip2px(this, 160f))
+        }
+
+        viewPager = findViewById(ResUtils.getResId(this, "yyxx_vp", "id"))
+        val fragmentManager = supportFragmentManager
+        //使用适配器将ViewPager和Fragment绑定在一起
+        val tabs = this.resources.getStringArray(ResUtils.getResId(this, "yyxx_login_tab", "array"))
+        val pagerAdapter = LoginFragmentPagerAdapter(tabs, fragmentManager)
+        viewPager.adapter = pagerAdapter
+        //将TabLayout与ViewPager绑定在一起
+        tabLayout.setupWithViewPager(viewPager)
+        leftSelect = ResUtils.getResId(this, "yyxx_tab_left_select", "drawable")
+        leftSelected = ResUtils.getResId(this, "yyxx_tab_left_selected", "drawable")
+        rightSelect = ResUtils.getResId(this, "yyxx_tab_right_select", "drawable")
+        rightSelected = ResUtils.getResId(this, "yyxx_tab_right_selected", "drawable")
+        setTabBackground(leftSelected, rightSelect)
+        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
+            override fun onTabSelected(tab: TabLayout.Tab?) {
+                when (tabLayout.selectedTabPosition) {
+                    0 -> setTabBackground(leftSelected, rightSelect)
+                    1 -> setTabBackground(leftSelect, rightSelected)
+                }
+            }
+
+            override fun onTabUnselected(tab: TabLayout.Tab?) {
+                if (pagerAdapter.currentFragment is LauncherFragment) {
+                    //TODO 收起下拉列表
+
+                }
+            }
+
+            override fun onTabReselected(tab: TabLayout.Tab?) {
+
+            }
+        })
+
+        loginContainer.visibility = View.GONE
+    }
+
+    private fun setTabBackground(left: Int, right: Int) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            val tabStrip = tabLayout.getChildAt(0) as ViewGroup
+            val tabView1 = tabStrip.getChildAt(0)
+            val tabView2 = tabStrip.getChildAt(1)
+            if (tabView1 != null) {
+                val paddingStart = tabView1.paddingStart
+                val paddingTop = tabView1.paddingTop
+                val paddingEnd = tabView1.paddingEnd
+                val paddingBottom = tabView1.paddingBottom
+                ViewCompat.setBackground(
+                    tabView1, ContextCompat.getDrawable(tabView1.context, left)
+                )
+                ViewCompat.setPaddingRelative(tabView1, paddingStart, paddingTop, paddingEnd, paddingBottom)
+            }
+            if (tabView2 != null) {
+                val paddingStart = tabView2.paddingStart
+                val paddingTop = tabView2.paddingTop
+                val paddingEnd = tabView2.paddingEnd
+                val paddingBottom = tabView2.paddingBottom
+                ViewCompat.setBackground(tabView2, ContextCompat.getDrawable(tabView2.context, right))
+                ViewCompat.setPaddingRelative(tabView2, paddingStart, paddingTop, paddingEnd, paddingBottom)
+            }
+        }
+    }
+
+    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
+        ev?.let {
+            if (it.action == MotionEvent.ACTION_DOWN) {
+                val v = currentFocus
+                if (isShouldHideInput(v, it)) {
+                    val imm =
+                        this@LoginActivity.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
+                    imm.hideSoftInputFromWindow(v!!.windowToken, 0)
+                }
+                return super.dispatchTouchEvent(it)
+            }
+        }
+        // 必不可少,否则所有的组件都不会有TouchEvent了
+        return if (window.superDispatchTouchEvent(ev)) {
+            true
+        } else onTouchEvent(ev)
+    }
+
+    private fun hideBar() {
+        // The UI options currently enabled are represented by a bitfield.
+        // getSystemUiVisibility() gives us that bitfield.
+        val uiOptions = window.decorView.systemUiVisibility
+        var newUiOptions = uiOptions
+        val isImmersiveModeEnabled = uiOptions or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY == uiOptions
+        if (!isImmersiveModeEnabled) {
+            if (Build.VERSION.SDK_INT >= 14) {
+                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+            }
+            if (Build.VERSION.SDK_INT >= 16) {
+                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_FULLSCREEN
+            }
+            if (Build.VERSION.SDK_INT >= 18) {
+                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+            }
+            window.decorView.systemUiVisibility = newUiOptions
+        }
+    }
+
+
+    private fun isShouldHideInput(v: View?, event: MotionEvent): Boolean {
+        if (v is EditText) {
+            val leftTop = intArrayOf(0, 0)
+            //获取输入框当前的location位置
+            v.getLocationInWindow(leftTop)
+            val left = leftTop[0]
+            val top = leftTop[1]
+            val bottom = top + v.getHeight()
+            val right = left + v.getWidth()
+            // 点击的是输入框区域,保留点击EditText的事件
+            return event.x <= left || event.x >= right || event.y <= top || event.y >= bottom
+        }
+        return false
+    }
+
+    private fun hideChooseDialog() {
+        chooseDialog?.apply {
+            dismiss()
+            chooseDialog = null
+        }
+    }
+
+    override fun onClick(v: View?) {
+        v?.apply {
+            when (tag as Int) {
+                ClickType.ACTION_GOOGLE_MODE -> userSignInImpl.googleLogin(this@LoginActivity)
+                ClickType.ACTION_FACEBOOK_MODE -> userSignInImpl.facebookLogin(this@LoginActivity)
+                ClickType.ACTION_ACCOUNT_MODE -> {
+                    chooseDialog?.dismiss()
+                    chooseDialog = null
+                    loginContainer.visibility = View.VISIBLE
+                }
+            }
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+        hideBar()
+    }
+
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        super.onActivityResult(requestCode, resultCode, data)
+        data?.apply {
+            userSignInImpl.onSignInResult(requestCode, resultCode, this)
+        }
+    }
+
+
+    companion object {
+
+        private var implCallback: IImplCallback? = null
+
+        fun login(activity: Activity, isAuto: Boolean, callback: IImplCallback) {
+            implCallback = callback
+            activity.startActivity(Intent(activity, LoginActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+        }
+    }
+
+
+}

+ 40 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/login/LoginFragmentPagerAdapter.kt

@@ -0,0 +1,40 @@
+package cn.yyxx.columbus.core.impl.login
+
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentPagerAdapter
+import cn.yyxx.columbus.core.impl.login.fragment.LauncherFragment
+import cn.yyxx.columbus.core.impl.login.fragment.RegisterFragment
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class LoginFragmentPagerAdapter constructor(private val titles: Array<String>, fm: FragmentManager, behavior: Int = 0) : FragmentPagerAdapter(fm, behavior) {
+
+    var currentFragment: Fragment? = null
+        private set
+
+    override fun getCount(): Int {
+        return titles.size
+    }
+
+    override fun getItem(position: Int): Fragment {
+        return if (position == 1) {
+            RegisterFragment()
+        } else {
+            LauncherFragment()
+        }
+    }
+
+    override fun getPageTitle(position: Int): CharSequence? {
+        return titles[position]
+    }
+
+    override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) {
+        currentFragment = `object` as Fragment
+        super.setPrimaryItem(container, position, `object`)
+    }
+
+}

+ 137 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/login/UserSignInImpl.kt

@@ -0,0 +1,137 @@
+package cn.yyxx.columbus.core.impl.login
+
+import android.app.Activity
+import android.content.Intent
+import cn.yyxx.columbus.base.utils.Logger
+import cn.yyxx.columbus.base.utils.ParamsUtils
+import cn.yyxx.columbus.core.entity.LoginType
+import cn.yyxx.support.hawkeye.ToastUtils
+import com.facebook.*
+import com.facebook.login.LoginManager
+import com.facebook.login.LoginResult
+import com.google.android.gms.auth.api.signin.GoogleSignIn
+import com.google.android.gms.auth.api.signin.GoogleSignInAccount
+import com.google.android.gms.auth.api.signin.GoogleSignInClient
+import com.google.android.gms.auth.api.signin.GoogleSignInOptions
+import com.google.android.gms.common.ConnectionResult
+import com.google.android.gms.common.GoogleApiAvailability
+import com.google.android.gms.common.api.ApiException
+import com.google.android.gms.tasks.Task
+import org.json.JSONException
+import org.json.JSONObject
+import java.util.*
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class UserSignInImpl constructor(val activity: LoginActivity, val callback: ISignInCallback) {
+
+    private var fbCallback: CallbackManager? = null
+    private var googleSignInClient: GoogleSignInClient? = null
+
+    init {
+        this.fbCallback = CallbackManager.Factory.create()
+        val googleServerClientId = ParamsUtils.getGoogleClientId(activity)
+        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+            .requestEmail()
+            .requestIdToken(googleServerClientId)
+            .requestId()
+            .requestProfile()
+            .build()
+        this.googleSignInClient = GoogleSignIn.getClient(activity, gso)
+    }
+
+    fun facebookLogin(activity: Activity) {
+        if (!FacebookSdk.isInitialized()) {
+            callback.onFailed("Facebook SDK 初始化失败")
+        }
+        //先注销账号,防止同一台设备有多个应用登录后直接回调onCancel
+        LoginManager.getInstance().logOut()
+        LoginManager.getInstance().registerCallback(fbCallback, object : FacebookCallback<LoginResult> {
+            override fun onSuccess(result: LoginResult?) {
+                result?.apply {
+                    try {
+                        val jsonObject = JSONObject()
+                        jsonObject.put("login_type", LoginType.TYPE_FACEBOOK_LOGIN)
+                        jsonObject.put("third_plat_id", AccessToken.getCurrentAccessToken().userId)
+                        jsonObject.put("third_plat_token", AccessToken.getCurrentAccessToken().token)
+                        callback.onSuccess(jsonObject.toString())
+                    } catch (e: JSONException) {
+                        e.printStackTrace()
+                        callback.onFailed("Facebook登录异常")
+                    }
+                }
+            }
+
+            override fun onCancel() {
+                callback.onFailed("Facebook登录取消")
+            }
+
+            override fun onError(error: FacebookException?) {
+                error?.apply {
+                    Logger.e("FBLogin onError error : " + this.message)
+                }
+                callback.onFailed("Facebook登录失败")
+            }
+        })
+        LoginManager.getInstance().logInWithReadPermissions(activity, Collections.singletonList("public_profile"))
+    }
+
+    fun googleLogin(activity: Activity) {
+        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity) != ConnectionResult.SUCCESS) {
+            ToastUtils.toastInfo(activity, "Google Services is not available for this device")
+            callback.onFailed("谷歌登录服务不可用,登录失败")
+            return
+        }
+
+        googleSignInClient?.apply {
+            val intent = signInIntent
+            activity.startActivityForResult(intent, 10000)
+        }
+    }
+
+    private fun handleGoogleSignInResult(data: Intent) {
+        val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)
+        try {
+            val account = task.getResult(ApiException::class.java)
+            try {
+                val jsonObject = JSONObject()
+                jsonObject.put("login_type", LoginType.TYPE_GOOGLE_LOGIN)
+                jsonObject.put("third_plat_id", account?.id)
+                jsonObject.put("third_plat_token", account?.idToken)
+                callback.onSuccess(jsonObject.toString())
+            } catch (e: JSONException) {
+                e.printStackTrace()
+                callback.onFailed("Google登录异常")
+            }
+        } catch (e: ApiException) {
+            e.printStackTrace()
+            callback.onFailed("Google登录异常")
+        }
+    }
+
+
+    fun guestLogin(activity: Activity) {
+
+    }
+
+    fun accountLogin(activity: Activity) {
+
+    }
+
+    fun onSignInResult(requestCode: Int, resultCode: Int, intent: Intent) {
+        fbCallback?.apply {
+            onActivityResult(requestCode, resultCode, intent)
+        }
+        if (requestCode == 10000) {
+            handleGoogleSignInResult(intent)
+        }
+    }
+
+    interface ISignInCallback {
+        fun onSuccess(result: String)
+
+        fun onFailed(result: String)
+    }
+}

+ 177 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/login/fragment/LauncherFragment.kt

@@ -0,0 +1,177 @@
+package cn.yyxx.columbus.core.impl.login.fragment
+
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import cn.yyxx.columbus.core.entity.ClickType
+import cn.yyxx.columbus.core.impl.SdkBridgeImpl
+import cn.yyxx.columbus.core.impl.login.LoginActivity
+import cn.yyxx.columbus.core.ui.EventEditText
+import cn.yyxx.columbus.core.ui.dialog.AgreementDialog
+import cn.yyxx.support.ResUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class LauncherFragment : Fragment(), View.OnClickListener {
+
+    private lateinit var mView: View
+
+    private lateinit var loginImpl: LoginActivity
+
+    private lateinit var eetAccount: EventEditText
+    private lateinit var eetPwd: EventEditText
+
+    private lateinit var tvForget: TextView
+
+    private lateinit var btnLauncher: Button
+
+    private lateinit var ivCheck: ImageView
+    private lateinit var tvAgreement: TextView
+
+    private lateinit var ivGoogle: ImageView
+    private lateinit var ivFacebook: ImageView
+    private lateinit var ivGuest: ImageView
+
+    private var imgUp = 0
+    private var imgDown = 0
+    private var imgShow = 0
+    private var imgHide = 0
+    private var imgCheck = 0
+    private var imgUnCheck = 0
+
+    private var check = true
+    private var isShowText = false
+
+    private var agreementDialog: AgreementDialog? = null
+
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        super.onCreateView(inflater, container, savedInstanceState)
+        loginImpl = requireActivity() as LoginActivity
+        mView = inflater.inflate(ResUtils.getResId(requireActivity(), "yyxx_login_launcher", "layout"), container, false)
+        initView(mView)
+        return mView
+    }
+
+    private fun initView(view: View) {
+        imgUp = ResUtils.getResId(requireActivity(), "yyxx_pack_up_img", "drawable")
+        imgDown = ResUtils.getResId(requireActivity(), "yyxx_pack_down_img", "drawable")
+        imgShow = ResUtils.getResId(requireActivity(), "yyxx_show_img", "drawable")
+        imgHide = ResUtils.getResId(requireActivity(), "yyxx_hide_img", "drawable")
+        imgCheck = ResUtils.getResId(requireActivity(), "yyxx_check_img", "drawable")
+        imgUnCheck = ResUtils.getResId(requireActivity(), "yyxx_uncheck_img", "drawable")
+
+        eetAccount = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_eet_account", "id"))
+        eetAccount.apply {
+            leftImageView.setBackgroundResource(ResUtils.getResId(requireActivity(), "yyxx_account_img", "drawable"))
+            leftImageView.visibility = View.VISIBLE
+            editText.setHint(ResUtils.getResId(requireActivity(), "yyxx_hint_account", "string"))
+            rightImageView.setOnClickListener {
+                //changeAccountList()
+            }
+        }
+
+        eetPwd = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_eet_pwd", "id"))
+        eetPwd.apply {
+            leftImageView.setBackgroundResource(ResUtils.getResId(requireActivity(), "yyxx_pwd_img", "drawable"))
+            leftImageView.visibility = View.VISIBLE
+            editText.setHint(ResUtils.getResId(requireActivity(), "yyxx_hint_pwd", "string"))
+            rightImageView.setBackgroundResource(imgShow)
+            rightImageView.visibility = View.VISIBLE
+            rightImageView.setOnClickListener {
+                if (!isShowText) {
+                    isShowText = true
+                    rightImageView.setBackgroundResource(imgHide)
+                    editText.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+                } else {
+                    isShowText = false
+                    rightImageView.setBackgroundResource(imgShow)
+                    editText.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
+                }
+                editText.setSelection(editText.length())
+            }
+        }
+
+        tvForget = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_tv_forget", "id"))
+
+        btnLauncher = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_btn_launcher", "id"))
+
+        ivCheck = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_iv_check", "id"))
+        tvAgreement = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_tv_agreement", "id"))
+        if (SdkBridgeImpl.initBean.privacyCfg.switch == 0) {
+            ivCheck.visibility = View.GONE
+            tvAgreement.visibility = View.GONE
+        } else {
+            ivCheck.visibility = View.VISIBLE
+            tvAgreement.visibility = View.VISIBLE
+        }
+
+        ivGoogle = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_iv_google", "id"))
+        ivFacebook = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_iv_facebook", "id"))
+        ivGuest = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_iv_guest", "id"))
+
+        initViewAction()
+        initViewListener()
+    }
+
+    private fun initViewAction() {
+        tvForget.tag = ClickType.ACTION_FORGET
+        btnLauncher.tag = ClickType.ACTION_LAUNCHER
+        ivCheck.tag = ClickType.ACTION_CLICK_CHECK
+        tvAgreement.tag = ClickType.ACTION_CLICK_AGREEMENT
+        ivGoogle.tag = ClickType.ACTION_GOOGLE_MODE
+        ivFacebook.tag = ClickType.ACTION_FACEBOOK_MODE
+        ivGuest.tag = ClickType.ACTION_GUEST_MODE
+    }
+
+    private fun initViewListener() {
+
+        tvForget.setOnClickListener(this)
+        btnLauncher.setOnClickListener(this)
+        ivCheck.setOnClickListener(this)
+        tvAgreement.setOnClickListener(this)
+        ivGoogle.setOnClickListener(this)
+        ivFacebook.setOnClickListener(this)
+        ivGuest.setOnClickListener(this)
+
+    }
+
+    private fun changeCheck() {
+        if (check) {
+            check = false
+            ivCheck.setBackgroundResource(imgUnCheck)
+        } else {
+            check = true
+            ivCheck.setBackgroundResource(imgCheck)
+        }
+    }
+
+    override fun onClick(v: View?) {
+        v?.apply {
+            when (tag as Int) {
+//                ClickType.ACTION_FORGET->
+//                ClickType.ACTION_LAUNCHER->
+                ClickType.ACTION_CLICK_CHECK -> changeCheck()
+                ClickType.ACTION_CLICK_AGREEMENT -> {
+                    agreementDialog?.apply {
+                        dismiss()
+                        agreementDialog = null
+                    }
+                    agreementDialog = AgreementDialog(requireContext(), SdkBridgeImpl.initBean.privacyCfg.url)
+                    agreementDialog?.show()
+                }
+                ClickType.ACTION_GOOGLE_MODE -> loginImpl.userSignInImpl.googleLogin(requireActivity())
+                ClickType.ACTION_FACEBOOK_MODE -> loginImpl.userSignInImpl.facebookLogin(requireActivity())
+
+            }
+        }
+    }
+}

+ 141 - 0
library_core/src/main/java/cn/yyxx/columbus/core/impl/login/fragment/RegisterFragment.kt

@@ -0,0 +1,141 @@
+package cn.yyxx.columbus.core.impl.login.fragment
+
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import cn.yyxx.columbus.core.entity.ClickType
+import cn.yyxx.columbus.core.impl.SdkBridgeImpl
+import cn.yyxx.columbus.core.ui.EventEditText
+import cn.yyxx.columbus.core.ui.dialog.AgreementDialog
+import cn.yyxx.support.ResUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class RegisterFragment : Fragment(), View.OnClickListener {
+
+    private lateinit var mView: View
+
+    private lateinit var eetAccount: EventEditText
+    private lateinit var eetPwd: EventEditText
+
+    private lateinit var btnRegister: Button
+
+    private lateinit var ivCheck: ImageView
+    private lateinit var tvAgreement: TextView
+
+    private var imgShow = 0
+    private var imgHide = 0
+    private var imgCheck = 0
+    private var imgUnCheck = 0
+
+    private var check = true
+    private var isShowText = false
+
+    private var agreementDialog: AgreementDialog? = null
+
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        super.onCreateView(inflater, container, savedInstanceState)
+        mView = inflater.inflate(ResUtils.getResId(requireActivity(), "yyxx_login_register", "layout"), container, false)
+        initView(mView)
+        return mView
+    }
+
+    private fun initView(view: View) {
+        imgShow = ResUtils.getResId(requireActivity(), "yyxx_show_img", "drawable")
+        imgHide = ResUtils.getResId(requireActivity(), "yyxx_hide_img", "drawable")
+        imgCheck = ResUtils.getResId(requireActivity(), "yyxx_check_img", "drawable")
+        imgUnCheck = ResUtils.getResId(requireActivity(), "yyxx_uncheck_img", "drawable")
+
+        eetAccount = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_eet_account", "id"))
+        eetAccount.apply {
+            leftImageView.setBackgroundResource(ResUtils.getResId(requireActivity(), "yyxx_account_img", "drawable"))
+            leftImageView.visibility = View.VISIBLE
+            editText.setHint(ResUtils.getResId(requireActivity(), "yyxx_hint_register_account", "string"))
+        }
+
+        eetPwd = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_eet_pwd", "id"))
+        eetPwd.apply {
+            leftImageView.setBackgroundResource(ResUtils.getResId(requireActivity(), "yyxx_pwd_img", "drawable"))
+            leftImageView.visibility = View.VISIBLE
+            editText.setHint(ResUtils.getResId(requireActivity(), "yyxx_hint_register_pwd", "string"))
+            rightImageView.setBackgroundResource(imgShow)
+            rightImageView.visibility = View.VISIBLE
+            rightImageView.setOnClickListener {
+                if (!isShowText) {
+                    isShowText = true
+                    rightImageView.setBackgroundResource(imgHide)
+                    editText.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+                } else {
+                    isShowText = false
+                    rightImageView.setBackgroundResource(imgShow)
+                    editText.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
+                }
+                editText.setSelection(editText.length())
+            }
+        }
+
+        btnRegister = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_btn_register", "id"))
+
+        ivCheck = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_iv_check", "id"))
+        tvAgreement = view.findViewById(ResUtils.getResId(requireActivity(), "yyxx_tv_agreement", "id"))
+        if (SdkBridgeImpl.initBean.privacyCfg.switch == 0) {
+            ivCheck.visibility = View.GONE
+            tvAgreement.visibility = View.GONE
+        } else {
+            ivCheck.visibility = View.VISIBLE
+            tvAgreement.visibility = View.VISIBLE
+        }
+
+        initViewAction()
+        initViewListener()
+    }
+
+    private fun initViewAction() {
+        btnRegister.tag = ClickType.ACTION_REGISTER
+        ivCheck.tag = ClickType.ACTION_CLICK_CHECK
+        tvAgreement.tag = ClickType.ACTION_CLICK_AGREEMENT
+
+    }
+
+    private fun initViewListener() {
+        btnRegister.setOnClickListener(this)
+        ivCheck.setOnClickListener(this)
+        tvAgreement.setOnClickListener(this)
+    }
+
+    private fun changeCheck() {
+        if (check) {
+            check = false
+            ivCheck.setBackgroundResource(imgUnCheck)
+        } else {
+            check = true
+            ivCheck.setBackgroundResource(imgCheck)
+        }
+    }
+
+    override fun onClick(v: View?) {
+        v?.apply {
+            when (tag as Int) {
+                ClickType.ACTION_CLICK_CHECK -> changeCheck()
+                ClickType.ACTION_CLICK_AGREEMENT -> {
+                    agreementDialog?.apply {
+                        dismiss()
+                        agreementDialog = null
+                    }
+                    agreementDialog = AgreementDialog(requireContext(), SdkBridgeImpl.initBean.privacyCfg.url)
+                    agreementDialog?.show()
+                }
+            }
+        }
+
+    }
+}

+ 19 - 0
library_core/src/main/java/cn/yyxx/columbus/core/internal/IEventObserver.kt

@@ -0,0 +1,19 @@
+package cn.yyxx.columbus.core.internal
+
+import android.content.Context
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+interface IEventObserver {
+
+    fun onInitialize(context: Context)
+
+    fun onLogin(context: Context)
+
+    fun onRegister(context: Context)
+
+    fun onBillingFinish(context: Context)
+
+}

+ 10 - 0
library_core/src/main/java/cn/yyxx/columbus/core/internal/IImplCallback.kt

@@ -0,0 +1,10 @@
+package cn.yyxx.columbus.core.internal
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+interface IImplCallback {
+
+    fun onResult(code: Int, result: String)
+}

+ 45 - 0
library_core/src/main/java/cn/yyxx/columbus/core/linking/Linking.kt

@@ -0,0 +1,45 @@
+package cn.yyxx.columbus.core.linking
+
+import android.content.Context
+import cn.yyxx.columbus.core.internal.IEventObserver
+import cn.yyxx.columbus.core.linking.channel.LinkingAdjustImpl
+import cn.yyxx.columbus.core.linking.channel.LinkingFirebaseImpl
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class Linking {
+
+    private val observers: MutableList<IEventObserver> = mutableListOf()
+
+    fun attach(context: Context) {
+        observers.add(LinkingAdjustImpl())
+        observers.add(LinkingFirebaseImpl())
+    }
+
+    fun detach() {
+        if (!observers.isNullOrEmpty()) {
+            observers.clear()
+        }
+    }
+
+
+    companion object {
+        fun getInstance(): Linking {
+            return LinkingHolder.INSTANCE
+        }
+
+
+        private object LinkingHolder {
+            val INSTANCE: Linking = Linking()
+        }
+
+        /**
+         * 防止单例对象在反序列化时重新生成对象
+         */
+        private fun readResolve(): Any {
+            return LinkingHolder.INSTANCE
+        }
+    }
+}

+ 27 - 0
library_core/src/main/java/cn/yyxx/columbus/core/linking/channel/LinkingAdjustImpl.kt

@@ -0,0 +1,27 @@
+package cn.yyxx.columbus.core.linking.channel
+
+import android.content.Context
+import cn.yyxx.columbus.core.internal.IEventObserver
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class LinkingAdjustImpl : IEventObserver {
+
+    override fun onInitialize(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onLogin(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onRegister(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onBillingFinish(context: Context) {
+        TODO("Not yet implemented")
+    }
+}

+ 26 - 0
library_core/src/main/java/cn/yyxx/columbus/core/linking/channel/LinkingFirebaseImpl.kt

@@ -0,0 +1,26 @@
+package cn.yyxx.columbus.core.linking.channel
+
+import android.content.Context
+import cn.yyxx.columbus.core.internal.IEventObserver
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+class LinkingFirebaseImpl : IEventObserver {
+    override fun onInitialize(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onLogin(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onRegister(context: Context) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onBillingFinish(context: Context) {
+        TODO("Not yet implemented")
+    }
+}

+ 45 - 0
library_core/src/main/java/cn/yyxx/columbus/core/network/Host.kt

@@ -0,0 +1,45 @@
+package cn.yyxx.columbus.core.network
+
+import android.content.Context
+import cn.yyxx.support.HostModelUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/17
+ */
+object Host {
+
+    private const val DEFAULT_ONLINE_HOST = ""
+    private const val DEFAULT_TEST_HOST = ""
+
+    private var HOST = ""
+
+    /**
+     * 默认线上环境
+     */
+    var IP_MODEL = 3
+
+    var BASIC_URL_INIT_SDK = ""
+    var BASIC_URL_LOGIN = ""
+    var BASIC_URL_THIRD_PART_LOGIN = ""
+    var BASIC_URL_REGISTER = ""
+    var BASIC_URL_FORGET_PWD = ""
+    var BASIC_URL_GET_ORDER_ID = ""
+    var BASIC_URL_NOTIFY_ORDER = ""
+    var BASIC_URL_NOTIFY_REWARD = ""
+    var BASIC_URL_SUBMIT_ROLE_INFO = ""
+
+
+    fun initHostModel(context: Context) {
+        IP_MODEL = HostModelUtils.getHostModel(context)
+        setDefaultHost()
+    }
+
+    fun setDefaultHost() {
+        when (IP_MODEL) {
+            HostModelUtils.ENV_TEST -> HOST = DEFAULT_TEST_HOST
+            HostModelUtils.ENV_ONLINE -> HOST = DEFAULT_ONLINE_HOST
+        }
+        //初始化接口路由
+    }
+}

+ 58 - 0
library_core/src/main/java/cn/yyxx/columbus/core/ui/EventEditText.kt

@@ -0,0 +1,58 @@
+package cn.yyxx.columbus.core.ui
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.EditText
+import android.widget.ImageView
+import androidx.constraintlayout.widget.ConstraintLayout
+import cn.yyxx.support.ResUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class EventEditText : ConstraintLayout, View.OnFocusChangeListener {
+    lateinit var focusView: View
+        private set
+    lateinit var leftImageView: ImageView
+        private set
+    lateinit var rightImageView: ImageView
+        private set
+    lateinit var editText: EditText
+        private set
+
+    constructor(context: Context) : this(context, null)
+
+    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+
+    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
+        initView(context)
+    }
+
+    private fun initView(context: Context) {
+        LayoutInflater.from(context).inflate(ResUtils.getResId(context, "yyxx_event_edit_text", "layout"), this)
+
+        focusView = findViewById(ResUtils.getResId(context, "yyxx_eet_focus_view", "id"))
+        focusView.visibility = View.GONE
+
+        leftImageView = findViewById(ResUtils.getResId(context, "yyxx_eet_iv_left", "id"))
+        leftImageView.visibility = View.GONE
+
+        editText = findViewById(ResUtils.getResId(context, "yyxx_eet_input", "id"))
+        editText.onFocusChangeListener = this
+
+        rightImageView = findViewById(ResUtils.getResId(context, "yyxx_eet_iv_right", "id"))
+        rightImageView.visibility = View.GONE
+
+    }
+
+    override fun onFocusChange(v: View?, hasFocus: Boolean) {
+        if (hasFocus) {
+            focusView.visibility = View.VISIBLE
+        } else {
+            focusView.visibility = View.GONE
+        }
+    }
+}

+ 29 - 0
library_core/src/main/java/cn/yyxx/columbus/core/ui/NoScrollViewPager.kt

@@ -0,0 +1,29 @@
+package cn.yyxx.columbus.core.ui
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import androidx.viewpager.widget.ViewPager
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class NoScrollViewPager : ViewPager {
+
+    var scrollEnable: Boolean = true
+
+    constructor(context: Context) : this(context, null)
+
+    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+
+
+    override fun onTouchEvent(ev: MotionEvent?): Boolean {
+        return this.scrollEnable && super.onTouchEvent(ev)
+    }
+
+    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
+        return this.scrollEnable && super.onInterceptTouchEvent(ev)
+    }
+
+}

+ 86 - 0
library_core/src/main/java/cn/yyxx/columbus/core/ui/dialog/AgreementDialog.kt

@@ -0,0 +1,86 @@
+package cn.yyxx.columbus.core.ui.dialog
+
+import android.app.Dialog
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.view.*
+import android.webkit.CookieSyncManager
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.widget.FrameLayout
+import android.widget.ImageView
+import cn.yyxx.columbus.core.entity.ClickType
+import cn.yyxx.support.ResUtils
+import cn.yyxx.support.device.DeviceInfoUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/19
+ */
+class AgreementDialog constructor(context: Context, url: String) : Dialog(context) {
+
+    init {
+        initView(context)
+        initWebView(url)
+    }
+
+    private fun initView(context: Context) {
+        setCanceledOnTouchOutside(false)
+        window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+        requestWindowFeature(Window.FEATURE_NO_TITLE)
+
+        val view = LayoutInflater.from(context).inflate(ResUtils.getResId(context, "yyxx_agreement_dialog", "layout"), null)
+        setContentView(view)
+
+        val attr = window?.attributes as WindowManager.LayoutParams
+        attr.height = ViewGroup.LayoutParams.WRAP_CONTENT
+        attr.width = ViewGroup.LayoutParams.WRAP_CONTENT
+        attr.gravity = Gravity.CENTER
+
+        val ivReturn: ImageView = findViewById(ResUtils.getResId(context, "yyxx_iv_return", "id"))
+        ivReturn.apply {
+            tag = ClickType.ACTION_RETURN
+            setOnClickListener {
+                this@AgreementDialog.dismiss()
+            }
+        }
+    }
+
+    private fun initWebView(url: String) {
+        val webView = WebView(context)
+        webView.isVerticalScrollBarEnabled = true
+        webView.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
+        val webViewContainer = findViewById<FrameLayout>(ResUtils.getResId(context, "yyxx_webview_container", "id"))
+        webViewContainer.addView(webView)
+
+        val webSetting = webView.settings
+        webSetting.allowFileAccess = true
+        webSetting.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
+        webSetting.setSupportZoom(true)
+        webSetting.saveFormData = true
+        webSetting.savePassword = true
+        webSetting.builtInZoomControls = false
+        webSetting.useWideViewPort = true
+        webSetting.setSupportMultipleWindows(false)
+        webSetting.setAppCacheEnabled(true)
+        webSetting.domStorageEnabled = true
+        webSetting.javaScriptEnabled = true
+        webSetting.setGeolocationEnabled(true)
+        webSetting.setAppCacheMaxSize(Long.MAX_VALUE)
+        webSetting.setAppCachePath(context.getDir("appcache", 0).path)
+        webSetting.databasePath = context.getDir("databases", 0).path
+        webSetting.setGeolocationDatabasePath(context.getDir("geolocation", 0).path)
+        webSetting.pluginState = WebSettings.PluginState.ON_DEMAND
+        CookieSyncManager.createInstance(context)
+        CookieSyncManager.getInstance().sync()
+
+        if (DeviceInfoUtils.isNetworkConnected(context)) {
+            webView.loadUrl(url)
+        } else {
+            //这种写法可以正确解码
+            webView.loadData("网络异常,请检查重试", "text/html; charset=UTF-8", null)
+        }
+    }
+
+}

+ 58 - 0
library_core/src/main/java/cn/yyxx/columbus/core/ui/dialog/ChooseLoginDialog.kt

@@ -0,0 +1,58 @@
+package cn.yyxx.columbus.core.ui.dialog
+
+import android.app.Dialog
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.view.*
+import android.widget.ImageView
+import cn.yyxx.support.ResUtils
+
+/**
+ * @author #Suyghur.
+ * Created on 2021/06/18
+ */
+class ChooseLoginDialog(context: Context) : Dialog(context) {
+
+//    lateinit var typeGoogle: ConstraintLayout
+//        private set
+//    lateinit var typeFacebook: ConstraintLayout
+//        private set
+//    lateinit var typeAccount: ConstraintLayout
+//        private set
+//    lateinit var typeGuest: ConstraintLayout
+//        private set
+
+    lateinit var typeGoogle: ImageView
+        private set
+    lateinit var typeFacebook: ImageView
+        private set
+    lateinit var typeAccount: ImageView
+        private set
+    lateinit var typeGuest: ImageView
+        private set
+
+    init {
+        setCanceledOnTouchOutside(false)
+        window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+        requestWindowFeature(Window.FEATURE_NO_TITLE)
+        initView(context)
+    }
+
+    private fun initView(context: Context) {
+
+        val view: View = LayoutInflater.from(context).inflate(ResUtils.getResId(context, "yyxx_choose_login_dialog", "layout"), null)
+        setContentView(view)
+
+        val attr = window?.attributes as WindowManager.LayoutParams
+        //设置dialog 在布局中的位置
+        attr.height = ViewGroup.LayoutParams.WRAP_CONTENT
+        attr.width = ViewGroup.LayoutParams.WRAP_CONTENT
+        attr.gravity = Gravity.CENTER
+
+        typeGoogle = view.findViewById(ResUtils.getResId(context, "yyxx_iv_google", "id"))
+        typeFacebook = view.findViewById(ResUtils.getResId(context, "yyxx_iv_facebook", "id"))
+        typeAccount = view.findViewById(ResUtils.getResId(context, "yyxx_iv_account", "id"))
+        typeGuest = view.findViewById(ResUtils.getResId(context, "yyxx_iv_guest", "id"))
+    }
+}

BIN
library_core/src/main/res/drawable-xhdpi/yyxx_account_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_account_login_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_check_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_facebook_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_facebook_login_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_google_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_google_login_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_guest_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_guest_login_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_hide_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_pack_down_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_pack_up_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_pwd_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_return_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_show_img.png


BIN
library_core/src/main/res/drawable-xhdpi/yyxx_uncheck_img.png


+ 5 - 0
library_core/src/main/res/drawable/yyxx_btn_black_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_black" />
+</shape>

+ 5 - 0
library_core/src/main/res/drawable/yyxx_btn_blue_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_blue" />
+</shape>

+ 5 - 0
library_core/src/main/res/drawable/yyxx_btn_green_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_green" />
+</shape>

+ 5 - 0
library_core/src/main/res/drawable/yyxx_btn_green_blue_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_green_blue" />
+</shape>

+ 8 - 0
library_core/src/main/res/drawable/yyxx_btn_white_bg.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_white" />
+<!--    <stroke-->
+<!--        android:width="1dp"-->
+<!--        android:color="@color/yyxx_color_gray_30" />-->
+</shape>

+ 9 - 0
library_core/src/main/res/drawable/yyxx_et_frame_focused_bg.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <solid android:color="@color/yyxx_color_white" />
+    <corners android:radius="8dp" />
+    <stroke
+        android:width="1dp"
+        android:color="@color/yyxx_color_gray" />
+</shape>

+ 9 - 0
library_core/src/main/res/drawable/yyxx_et_frame_normal_bg.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <solid android:color="@color/yyxx_color_white" />
+    <corners android:radius="8dp" />
+    <stroke
+        android:width="1dp"
+        android:color="@color/yyxx_color_gray_30" />
+</shape>

+ 5 - 0
library_core/src/main/res/drawable/yyxx_et_frame_selector_bg.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/yyxx_et_frame_normal_bg" android:state_focused="false" />
+    <item android:drawable="@drawable/yyxx_et_frame_focused_bg" android:state_focused="true" />
+</selector>

+ 7 - 0
library_core/src/main/res/drawable/yyxx_login_panel_bg.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/yyxx_color_white_90" />
+</shape>
+
+

+ 8 - 0
library_core/src/main/res/drawable/yyxx_tab_left_select.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#DBDBDB" />
+    <corners android:topLeftRadius="8dp" />
+    <!--    <stroke-->
+    <!--        android:width="1dp"-->
+    <!--        android:color="@color/yyxx_color_white" />-->
+</shape>

+ 8 - 0
library_core/src/main/res/drawable/yyxx_tab_left_selected.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/yyxx_color_white" />
+    <corners android:topLeftRadius="8dp" />
+    <!--    <stroke-->
+    <!--        android:width="1dp"-->
+    <!--        android:color="@color/yyxx_color_white" />-->
+</shape>

+ 8 - 0
library_core/src/main/res/drawable/yyxx_tab_right_select.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#DBDBDB" />
+    <corners android:topRightRadius="8dp" />
+    <!--    <stroke-->
+    <!--        android:width="1dp"-->
+    <!--        android:color="@color/yyxx_color_white" />-->
+</shape>

+ 8 - 0
library_core/src/main/res/drawable/yyxx_tab_right_selected.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/yyxx_color_white" />
+    <corners android:topRightRadius="8dp" />
+    <!--    <stroke-->
+    <!--        android:width="1dp"-->
+    <!--        android:color="@color/yyxx_color_white" />-->
+</shape>

+ 8 - 0
library_core/src/main/res/drawable/yyxx_webview_border.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="8dp" />
+    <stroke
+        android:width="1dp"
+        android:color="@color/yyxx_color_gray_30" />
+</shape>

+ 59 - 0
library_core/src/main/res/layout/yyxx_agreement_dialog.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/yyxx_login_panel_bg">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_title_container"
+        android:layout_width="0dp"
+        android:layout_height="40dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/yyxx_iv_return"
+            android:layout_width="60dp"
+            android:layout_height="30dp"
+            android:background="@drawable/yyxx_return_img"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/yyxx_tv_agreement_title"
+            android:textColor="@color/yyxx_color_green_blue"
+            android:textSize="20sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="20dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_title_container">
+
+        <FrameLayout
+            android:id="@+id/yyxx_webview_container"
+            android:layout_width="match_parent"
+            android:layout_height="250dp"
+            android:background="@drawable/yyxx_webview_border"
+            android:padding="3dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 221 - 0
library_core/src/main/res/layout/yyxx_choose_login_dialog.xml

@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:background="@drawable/yyxx_login_panel_bg"
+    android:padding="30dp">
+
+    <ImageView
+        android:id="@+id/yyxx_iv_google"
+        android:layout_width="230dp"
+        android:layout_height="50dp"
+        android:background="@drawable/yyxx_google_login_img"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/yyxx_iv_facebook"
+        android:layout_width="230dp"
+        android:layout_height="50dp"
+        android:layout_marginTop="5dp"
+        android:background="@drawable/yyxx_facebook_login_img"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_iv_google" />
+
+    <ImageView
+        android:id="@+id/yyxx_iv_account"
+        android:layout_width="230dp"
+        android:layout_height="50dp"
+        android:layout_marginTop="5dp"
+        android:background="@drawable/yyxx_account_login_img"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_iv_facebook" />
+
+    <ImageView
+        android:id="@+id/yyxx_iv_guest"
+        android:layout_width="230dp"
+        android:layout_height="50dp"
+        android:layout_marginTop="5dp"
+        android:background="@drawable/yyxx_guest_login_img"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_iv_account" />
+
+
+    <!--    <androidx.constraintlayout.widget.ConstraintLayout-->
+    <!--        android:id="@+id/yyxx_cl_google"-->
+    <!--        android:layout_width="250dp"-->
+    <!--        android:layout_height="45dp"-->
+    <!--        android:background="@drawable/yyxx_btn_white_bg"-->
+    <!--        app:layout_constraintBottom_toTopOf="@id/yyxx_cl_facebook"-->
+    <!--        app:layout_constraintEnd_toEndOf="parent"-->
+    <!--        app:layout_constraintStart_toStartOf="parent"-->
+    <!--        app:layout_constraintTop_toTopOf="parent">-->
+
+    <!--        <androidx.constraintlayout.widget.Guideline-->
+    <!--            android:id="@+id/yyxx_gl_google"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="wrap_content"-->
+    <!--            android:orientation="vertical"-->
+    <!--            app:layout_constraintGuide_percent="0.1"-->
+    <!--            app:layout_constraintStart_toStartOf="parent"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <ImageView-->
+    <!--            android:id="@+id/yyxx_iv_google"-->
+    <!--            android:layout_width="25dp"-->
+    <!--            android:layout_height="25dp"-->
+    <!--            android:background="@drawable/yyxx_google_type_img"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_gl_google"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <TextView-->
+    <!--            android:id="@+id/yyxx_tv_google"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="30dp"-->
+    <!--            android:layout_marginStart="10dp"-->
+    <!--            android:text="@string/yyxx_login_type_google"-->
+    <!--            android:textColor="@color/yyxx_color_gray"-->
+    <!--            android:textSize="20sp"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_iv_google"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+    <!--    </androidx.constraintlayout.widget.ConstraintLayout>-->
+
+    <!--    <androidx.constraintlayout.widget.ConstraintLayout-->
+    <!--        android:id="@+id/yyxx_cl_facebook"-->
+    <!--        android:layout_width="250dp"-->
+    <!--        android:layout_height="45dp"-->
+    <!--        android:layout_marginTop="15dp"-->
+    <!--        android:background="@drawable/yyxx_btn_blue_bg"-->
+    <!--        app:layout_constraintBottom_toTopOf="@id/yyxx_cl_account"-->
+    <!--        app:layout_constraintEnd_toEndOf="parent"-->
+    <!--        app:layout_constraintStart_toStartOf="parent"-->
+    <!--        app:layout_constraintTop_toBottomOf="@id/yyxx_cl_google">-->
+
+    <!--        <androidx.constraintlayout.widget.Guideline-->
+    <!--            android:id="@+id/yyxx_gl_facebook"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="wrap_content"-->
+    <!--            android:orientation="vertical"-->
+    <!--            app:layout_constraintGuide_percent="0.1"-->
+    <!--            app:layout_constraintStart_toStartOf="parent"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <ImageView-->
+    <!--            android:id="@+id/yyxx_iv_facebook"-->
+    <!--            android:layout_width="25dp"-->
+    <!--            android:layout_height="25dp"-->
+    <!--            android:background="@drawable/yyxx_facebook_type_img"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_gl_facebook"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <TextView-->
+    <!--            android:id="@+id/yyxx_tv_facebook"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="30dp"-->
+    <!--            android:layout_marginStart="10dp"-->
+    <!--            android:text="@string/yyxx_login_type_facebook"-->
+    <!--            android:textColor="@color/yyxx_color_white"-->
+    <!--            android:textSize="20sp"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_iv_facebook"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+    <!--    </androidx.constraintlayout.widget.ConstraintLayout>-->
+
+
+    <!--    <androidx.constraintlayout.widget.ConstraintLayout-->
+    <!--        android:id="@+id/yyxx_cl_account"-->
+    <!--        android:layout_width="250dp"-->
+    <!--        android:layout_height="45dp"-->
+    <!--        android:layout_marginTop="15dp"-->
+    <!--        android:background="@drawable/yyxx_btn_green_blue_bg"-->
+    <!--        app:layout_constraintBottom_toTopOf="@id/yyxx_cl_guest"-->
+    <!--        app:layout_constraintEnd_toEndOf="parent"-->
+    <!--        app:layout_constraintStart_toStartOf="parent"-->
+    <!--        app:layout_constraintTop_toBottomOf="@id/yyxx_cl_facebook">-->
+
+    <!--        <androidx.constraintlayout.widget.Guideline-->
+    <!--            android:id="@+id/yyxx_gl_account"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="wrap_content"-->
+    <!--            android:orientation="vertical"-->
+    <!--            app:layout_constraintGuide_percent="0.1"-->
+    <!--            app:layout_constraintStart_toStartOf="parent"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <ImageView-->
+    <!--            android:id="@+id/yyxx_iv_account"-->
+    <!--            android:layout_width="25dp"-->
+    <!--            android:layout_height="25dp"-->
+    <!--            android:background="@drawable/yyxx_account_type_img"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_gl_account"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <TextView-->
+    <!--            android:id="@+id/yyxx_tv_account"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="30dp"-->
+    <!--            android:layout_marginStart="10dp"-->
+    <!--            android:text="@string/yyxx_login_type_account"-->
+    <!--            android:textColor="@color/yyxx_color_white"-->
+    <!--            android:textSize="20sp"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_iv_account"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+    <!--    </androidx.constraintlayout.widget.ConstraintLayout>-->
+
+
+    <!--    <androidx.constraintlayout.widget.ConstraintLayout-->
+    <!--        android:id="@+id/yyxx_cl_guest"-->
+    <!--        android:layout_width="250dp"-->
+    <!--        android:layout_height="45dp"-->
+    <!--        android:layout_marginTop="15dp"-->
+    <!--        android:background="@drawable/yyxx_btn_green_bg"-->
+    <!--        app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--        app:layout_constraintEnd_toEndOf="parent"-->
+    <!--        app:layout_constraintStart_toStartOf="parent"-->
+    <!--        app:layout_constraintTop_toBottomOf="@id/yyxx_cl_account">-->
+
+    <!--        <androidx.constraintlayout.widget.Guideline-->
+    <!--            android:id="@+id/yyxx_gl_guest"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="wrap_content"-->
+    <!--            android:orientation="vertical"-->
+    <!--            app:layout_constraintGuide_percent="0.1"-->
+    <!--            app:layout_constraintStart_toStartOf="parent"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <ImageView-->
+    <!--            android:id="@+id/yyxx_iv_guest"-->
+    <!--            android:layout_width="25dp"-->
+    <!--            android:layout_height="25dp"-->
+    <!--            android:background="@drawable/yyxx_guest_type_img"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_gl_guest"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+
+    <!--        <TextView-->
+    <!--            android:id="@+id/yyxx_tv_guest"-->
+    <!--            android:layout_width="wrap_content"-->
+    <!--            android:layout_height="30dp"-->
+    <!--            android:layout_marginStart="10dp"-->
+    <!--            android:text="@string/yyxx_login_type_guest"-->
+    <!--            android:textColor="@color/yyxx_color_white"-->
+    <!--            android:textSize="20sp"-->
+    <!--            app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--            app:layout_constraintStart_toEndOf="@id/yyxx_iv_guest"-->
+    <!--            app:layout_constraintTop_toTopOf="parent" />-->
+    <!--    </androidx.constraintlayout.widget.ConstraintLayout>-->
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 70 - 0
library_core/src/main/res/layout/yyxx_event_edit_text.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/yyxx_et_frame_selector_bg">
+
+    <View
+        android:id="@+id/yyxx_eet_focus_view"
+        android:layout_width="2dp"
+        android:layout_height="26dp"
+        android:background="@color/yyxx_color_green_blue"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_bias="0.5" />
+
+    <ImageView
+        android:id="@+id/yyxx_eet_iv_left"
+        android:layout_width="14dp"
+        android:layout_height="14dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/yyxx_v_gl_15"
+        app:layout_constraintHorizontal_bias="0.5"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_bias="0.5" />
+
+    <EditText
+        android:id="@+id/yyxx_eet_input"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:background="@android:color/transparent"
+        android:imeOptions="flagNoExtractUi|flagNoFullscreen"
+        android:singleLine="true"
+        android:textColor="@color/yyxx_color_gray"
+        android:textColorHint="@color/yyxx_color_gray_50"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/yyxx_v_gl_85"
+        app:layout_constraintStart_toEndOf="@+id/yyxx_v_gl_15"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/yyxx_eet_iv_right"
+        android:layout_width="18dp"
+        android:layout_height="18dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@+id/yyxx_v_gl_85"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/yyxx_v_gl_15"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_percent="0.15"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/yyxx_v_gl_85"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_percent="0.85"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 44 - 0
library_core/src/main/res/layout/yyxx_login.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/yyxx_login_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/yyxx_color_gray_30">
+
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_cl_login"
+        android:layout_width="320dp"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="30dp"
+        android:layout_marginRight="30dp"
+        android:background="@drawable/yyxx_login_panel_bg"
+        android:visibility="visible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <com.google.android.material.tabs.TabLayout
+            android:id="@+id/yyxx_tl"
+            android:layout_width="match_parent"
+            android:layout_height="35dp"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:tabIndicatorHeight="0dp"
+            app:tabSelectedTextColor="@color/yyxx_color_green_blue"
+            app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget"
+            app:tabTextColor="@color/yyxx_color_gray" />
+
+        <cn.yyxx.columbus.core.ui.NoScrollViewPager
+            android:id="@+id/yyxx_vp"
+            android:layout_width="match_parent"
+            android:layout_height="250dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/yyxx_tl" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 135 - 0
library_core/src/main/res/layout/yyxx_login_launcher.xml

@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:background="@color/yyxx_transparent"
+    android:padding="20dp">
+
+    <cn.yyxx.columbus.core.ui.EventEditText
+        android:id="@+id/yyxx_eet_account"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:background="@drawable/yyxx_et_frame_selector_bg"
+        app:layout_constraintBottom_toTopOf="@+id/yyxx_eet_pwd"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <cn.yyxx.columbus.core.ui.EventEditText
+        android:id="@+id/yyxx_eet_pwd"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:layout_marginTop="5dp"
+        android:background="@drawable/yyxx_et_frame_selector_bg"
+        app:layout_constraintBottom_toTopOf="@id/yyxx_tv_forget"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_eet_account" />
+
+    <TextView
+        android:id="@+id/yyxx_tv_forget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="5dp"
+        android:autoLink="all"
+        android:text="@string/yyxx_tv_forget"
+        android:textColor="@color/yyxx_color_green_blue"
+        android:textSize="12sp"
+        android:textStyle="bold"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_eet_pwd" />
+
+    <Button
+        android:id="@+id/yyxx_btn_launcher"
+        style="?android:attr/borderlessButtonStyle"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:layout_marginTop="10dp"
+        android:background="@drawable/yyxx_btn_green_blue_bg"
+        android:text="@string/yyxx_tv_launcher"
+        android:textColor="@color/yyxx_color_white"
+        android:textSize="16sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_tv_forget" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_cl_agreement"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        app:layout_constraintBottom_toTopOf="@id/yyxx_btn_group"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_btn_launcher">
+
+        <ImageView
+            android:id="@+id/yyxx_iv_check"
+            android:layout_width="14dp"
+            android:layout_height="14dp"
+            android:background="@drawable/yyxx_check_img"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/yyxx_tv_agreement"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/yyxx_tv_agreement"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:text="@string/yyxx_tv_agreement"
+            android:textColor="@color/yyxx_color_gray"
+            android:textSize="12sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/yyxx_iv_check"
+            app:layout_constraintTop_toTopOf="parent" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_btn_group"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_cl_agreement">
+
+        <ImageView
+            android:id="@+id/yyxx_iv_google"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:background="@drawable/yyxx_google_img"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/yyxx_iv_facebook"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <ImageView
+            android:id="@+id/yyxx_iv_facebook"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:background="@drawable/yyxx_facebook_img"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/yyxx_iv_guest"
+            app:layout_constraintStart_toEndOf="@id/yyxx_iv_google"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <ImageView
+            android:id="@+id/yyxx_iv_guest"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:background="@drawable/yyxx_guest_img"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/yyxx_iv_facebook"
+            app:layout_constraintTop_toTopOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 82 - 0
library_core/src/main/res/layout/yyxx_login_register.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:background="@color/yyxx_transparent"
+    android:padding="20dp">
+
+    <cn.yyxx.columbus.core.ui.EventEditText
+        android:id="@+id/yyxx_eet_account"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:background="@drawable/yyxx_et_frame_selector_bg"
+        app:layout_constraintBottom_toTopOf="@+id/yyxx_eet_pwd"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <cn.yyxx.columbus.core.ui.EventEditText
+        android:id="@+id/yyxx_eet_pwd"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:layout_marginTop="5dp"
+        android:background="@drawable/yyxx_et_frame_selector_bg"
+        app:layout_constraintBottom_toTopOf="@id/yyxx_btn_register"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_eet_account" />
+
+
+    <Button
+        android:id="@+id/yyxx_btn_register"
+        style="?android:attr/borderlessButtonStyle"
+        android:layout_width="match_parent"
+        android:layout_height="35dp"
+        android:layout_marginTop="20dp"
+        android:background="@drawable/yyxx_btn_green_blue_bg"
+        android:text="@string/yyxx_tv_register"
+        android:textColor="@color/yyxx_color_white"
+        android:textSize="16sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_eet_pwd" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/yyxx_cl_agreement"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/yyxx_btn_register">
+
+        <ImageView
+            android:id="@+id/yyxx_iv_check"
+            android:layout_width="14dp"
+            android:layout_height="14dp"
+            android:background="@drawable/yyxx_check_img"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/yyxx_tv_agreement"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/yyxx_tv_agreement"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:text="@string/yyxx_tv_agreement"
+            android:textColor="@color/yyxx_color_gray"
+            android:textSize="12sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/yyxx_iv_check"
+            app:layout_constraintTop_toTopOf="parent" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 21 - 0
library_core/src/main/res/values/yyxx_colors.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="yyxx_transparent">#00FFFFFF</color>
+    <color name="yyxx_color_white">#FFFFFF</color>
+    <color name="yyxx_color_white_90">#E6FFFFFF</color>
+    <color name="yyxx_color_white_70">#B3FFFFFF</color>
+    <color name="yyxx_color_red">#FF4C2B</color>
+    <color name="yyxx_color_orange">#FF912A</color>
+    <color name="yyxx_color_orange_95">#F2FF912A</color>
+    <color name="yyxx_color_green_blue">#1DB1AD</color>
+    <color name="yyxx_color_green">#7EB944</color>
+    <color name="yyxx_color_blue">#3B5998</color>
+
+    <color name="yyxx_color_light_gray">#A2A2A2</color>
+    <color name="yyxx_color_black_gray">#3B3B3B</color>
+    <color name="yyxx_color_gray">#505050</color>
+    <color name="yyxx_color_gray_30">#4D505050</color>
+    <color name="yyxx_color_gray_50">#80505050</color>
+    <color name="yyxx_color_black_70">#B3000000</color>
+    <color name="yyxx_color_black">#000000</color>
+</resources>

+ 32 - 0
library_core/src/main/res/values/yyxx_strings.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string-array name="yyxx_login_tab">
+        <item>登入</item>
+        <item>註冊</item>
+    </string-array>
+
+    <string name="yyxx_login_type_google">Sign in with Google</string>
+    <string name="yyxx_login_type_facebook">Facebook</string>
+    <string name="yyxx_login_type_account">帳號登入</string>
+    <string name="yyxx_login_type_guest">快速登入</string>
+
+    <string name="yyxx_tv_forget"><u>忘記密碼?</u></string>
+    <string name="yyxx_tv_launcher">登入</string>
+    <string name="yyxx_tv_register">注冊</string>
+    <string name="yyxx_tv_confirm">確認</string>
+    <string name="yyxx_tv_agreement">我已閲讀並同意《會員條款及管理規章》</string>
+    <string name="yyxx_tv_agreement_title">會員條款及管理規章</string>
+
+    <string name="yyxx_title_forget">忘記密碼</string>
+    <string name="yyxx_title_agreement">會員條款及管理規章</string>
+
+    <string name="yyxx_hint_account">輸入您的帳號</string>
+    <string name="yyxx_hint_pwd">輸入您的密碼</string>
+    <string name="yyxx_hint_register_account">6~18字符,僅允許字母和數字</string>
+    <string name="yyxx_hint_register_pwd">6~18字符,僅允許字母和數字</string>
+    <string name="yyxx_hint_forget_account">請輸入您的帳號</string>
+    <string name="yyxx_hint_forget_phone">請輸入您的手機門號</string>
+
+
+</resources>

+ 16 - 0
library_core/src/main/res/values/yyxx_styles.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <style name="ColumbusTheme" parent="Theme.AppCompat.NoActionBar">
+        <item name="android:windowBackground">@color/yyxx_transparent</item>
+        <item name="background">@color/yyxx_transparent</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowFrame">@null</item>
+        <item name="windowActionBar">false</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="windowNoTitle">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:backgroundDimEnabled">false</item>
+    </style>
+</resources>

+ 1 - 0
settings.gradle

@@ -1,5 +1,6 @@
 rootProject.name = "Columbus"
 include ':demo'
 include ':library_base'
+//include ':library_comm'
 include ':library_core'
 

+ 22 - 0
test.pem

@@ -0,0 +1,22 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAVatPhPaZtxBkLBZDnOLf7no6
+VfnjBRMXhpOnWmkkDX4zurB/OKisYDFnR0UUVnKn717+absfLlDk9HZWBcTMznsU
+ju9fuXlu3Elr8HeI3en7E0KIQzxkY1GT1+qtZ+tCjWuyMmUw4vWpO8/MRU3f6nc4
+io3w+7N+dP24BIo0ZwIDAQAB
+-----END PUBLIC KEY-----
+
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCAVatPhPaZtxBkLBZDnOLf7no6VfnjBRMXhpOnWmkkDX4zurB/
+OKisYDFnR0UUVnKn717+absfLlDk9HZWBcTMznsUju9fuXlu3Elr8HeI3en7E0KI
+QzxkY1GT1+qtZ+tCjWuyMmUw4vWpO8/MRU3f6nc4io3w+7N+dP24BIo0ZwIDAQAB
+AoGABDrHeXNJV8u0tjQGcAuyl56rpguMIzUD4ubiZM0ATDaAE1uZ2XFUqOzVkjf8
+DLELlR4cW28yiVMLvAnNANsgXzpJNc9F8mQJvjdz5P3v5td4EQHkYm2m0/HtdCVP
+vdfzofCrmNy9uCGWr8H+wSBuA6ifOr3ym4QVlAJLJfx0BOkCQQCRP+lKn4oD3HFC
+bQVJNQGQo/I3TE+EcSMQ6apAl9D16w4mfk4uaA24cKtgB1HKjlB4bcOnY593IMl0
+JIXvWTtpAkEA4jAF8ptfc/nXgzyKrXLinJhbcoRKgY3FQJE3EqHj2Ynu2L/rrsTL
+pcOW130SNGwEu5Rkpg8W0FSC/T9u9TkHTwJAX0WnlS3+TjgLBkISRImDJEeVOdZR
+FhNLp+1Moh+yjYuHdZJFX8Uass8cadmDObSNbeC5hBMhZvdXjFnkjDFgeQJASdqy
+ZngTH9RJaWGgSmhD1CvvWCIYDdtTt/RyjhPsSQC/y2hHNWautC58F1qQUiufE/yt
+LIeqxFWD+9r1iP6ZAwJBAIiKQMh+eDZeCHJsR5IlJ3O9Y8JsIt2/LfonmIUpGdmt
+DvJtVQw5J5XA3Tk1GLLn32XCHQCpvHQLHMyhHSPGeEs=
+-----END RSA PRIVATE KEY-----

BIN
zkeystore/demo_yyxx.keystore


BIN
zkeystore/demo_yyxx_backup.keystore