├── .gitignore ├── .idea ├── $CACHE_FILE$ ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── dictionaries ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── stew │ │ └── kotlinbox │ │ ├── ADActivity.kt │ │ ├── KBApplication.kt │ │ ├── MainActivity.kt │ │ ├── asyncthird │ │ ├── ATConstants.kt │ │ ├── ApplicationAnchorTaskCreator.kt │ │ ├── Task1.kt │ │ ├── Task2.kt │ │ ├── Task3.kt │ │ ├── Task4.kt │ │ ├── Task5.kt │ │ ├── Task6.kt │ │ └── Task7.kt │ │ └── hooktest │ │ ├── HookClassLoader.kt │ │ └── ProxyClassLoader.kt │ └── res │ ├── layout │ ├── activity_main.xml │ ├── activity_splash.xml │ ├── drawlayout.xml │ └── layout_main_pop.xml │ ├── menu │ └── main_bottom_menu.xml │ ├── mipmap-hdpi │ └── ic_launcher.webp │ ├── mipmap-ldpi │ └── ic_launcher.webp │ ├── mipmap-mdpi │ └── ic_launcher.webp │ ├── mipmap-xhdpi │ └── ic_launcher.webp │ ├── mipmap-xxhdpi │ └── ic_launcher.webp │ ├── mipmap-xxxhdpi │ └── ic_launcher.webp │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── app_plugin ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── stew │ └── app_plugin │ ├── AppPlugin.kt │ ├── MTMethodVisitor.kt │ └── MTTransform.kt ├── build.gradle ├── dependencies.gradle ├── github_imgs ├── w1.jpeg ├── w2.jpeg ├── w3.jpeg ├── w4.jpeg ├── w5.jpeg └── w6.jpeg ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kb_common ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_common │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_common │ │ │ ├── base │ │ │ ├── BaseActivity.kt │ │ │ ├── BaseFragment.kt │ │ │ ├── BaseRepository.kt │ │ │ ├── BaseVMFragment.kt │ │ │ ├── BaseViewModel.kt │ │ │ └── FlowBaseRepository.kt │ │ │ ├── network │ │ │ ├── BaseResp.kt │ │ │ ├── BaseStateObserver.kt │ │ │ ├── CookieBean.kt │ │ │ ├── MyCookieJar.kt │ │ │ ├── RespStateData.kt │ │ │ └── RetrofitManager.kt │ │ │ ├── util │ │ │ ├── AppCommonUitl.kt │ │ │ ├── AppLogUtil.kt │ │ │ ├── Constants.kt │ │ │ ├── Extension.kt │ │ │ ├── KVUtil.kt │ │ │ ├── LoadingViewUtil.kt │ │ │ ├── StatusBarUtil.kt │ │ │ ├── ToastUtil.kt │ │ │ └── dynamic_loadso │ │ │ │ ├── DSLoadUtil.kt │ │ │ │ ├── LoadLibraryUtils.java │ │ │ │ ├── ShareReflectUtil.java │ │ │ │ └── elf │ │ │ │ ├── Dynamic32Structure.java │ │ │ │ ├── Dynamic64Structure.java │ │ │ │ ├── Elf.java │ │ │ │ ├── Elf32Header.java │ │ │ │ ├── Elf64Header.java │ │ │ │ ├── ElfParser.java │ │ │ │ ├── Program32Header.java │ │ │ │ ├── Program64Header.java │ │ │ │ ├── Section32Header.java │ │ │ │ └── Section64Header.java │ │ │ └── widget │ │ │ └── MySwipeRefreshLayout.kt │ └── res │ │ ├── drawable-night │ │ ├── selector_bottom_navigation.xml │ │ └── splash_windows_background.xml │ │ ├── drawable │ │ ├── app_icon.png │ │ ├── icon_1.webp │ │ ├── icon_2.webp │ │ ├── icon_3.webp │ │ ├── icon_4.webp │ │ ├── icon_avatar.webp │ │ ├── icon_back.webp │ │ ├── icon_box.webp │ │ ├── icon_collect_1.webp │ │ ├── icon_collect_2.webp │ │ ├── icon_exp_light.webp │ │ ├── icon_light.webp │ │ ├── icon_menu.webp │ │ ├── selector_bottom_navigation.xml │ │ ├── shape_10dp_blue.xml │ │ ├── shape_10dp_grey.xml │ │ ├── shape_10dp_grey2.xml │ │ ├── shape_10dp_white.xml │ │ ├── shape_10dp_white2.xml │ │ ├── shape_login_bg.xml │ │ └── splash_windows_background.xml │ │ ├── layout │ │ ├── common_loading_dialog.xml │ │ ├── foot_rv.xml │ │ └── last_rv.xml │ │ ├── values-night │ │ └── colors.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_common │ └── ExampleUnitTest.kt ├── kb_exp ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_exp │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── plugintest.apk │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── hookmalloc │ │ │ ├── CMakeLists.txt │ │ │ └── HookMalloc.cpp │ │ └── malloc │ │ │ ├── CMakeLists.txt │ │ │ └── TestMalloc.cpp │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_exp │ │ │ ├── ui │ │ │ ├── ExpActivity.kt │ │ │ └── exp │ │ │ │ ├── DmActivity.kt │ │ │ │ ├── DpActivity.kt │ │ │ │ ├── DsActivity.kt │ │ │ │ ├── NativeHookActivity.kt │ │ │ │ ├── PickImageActivity.kt │ │ │ │ ├── PluginActivity.kt │ │ │ │ ├── ProcessInfoActivity.kt │ │ │ │ ├── ProxyActivity.kt │ │ │ │ ├── RestartAppActivity.kt │ │ │ │ └── TestPluginApkActivity.kt │ │ │ └── util │ │ │ ├── AssetsUtil.kt │ │ │ ├── PluginLoadUtil.kt │ │ │ └── TestMallocUtil.kt │ ├── jniLibs │ │ └── arm64-v8a │ │ │ ├── libhookmalloc.so │ │ │ └── libtestmalloc.so │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── layout │ │ ├── activity_app.xml │ │ ├── activity_dm.xml │ │ ├── activity_dp.xml │ │ ├── activity_ds.xml │ │ ├── activity_exp.xml │ │ ├── activity_nh.xml │ │ ├── activity_pi.xml │ │ ├── activity_pick_image.xml │ │ ├── activity_plugin.xml │ │ ├── activity_proxy.xml │ │ └── activity_tp.xml │ │ └── values │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_exp │ └── ExampleUnitTest.kt ├── kb_home ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_home │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_home │ │ │ ├── adapter │ │ │ ├── BannerAdapter.kt │ │ │ ├── HomeItemClickListener.kt │ │ │ └── HomeRVAdapter.kt │ │ │ ├── api │ │ │ └── HomeApi.kt │ │ │ ├── bean │ │ │ ├── Article.kt │ │ │ └── Banner.kt │ │ │ ├── di │ │ │ └── HomeModule.kt │ │ │ ├── repo │ │ │ └── HomeRepo.kt │ │ │ ├── ui │ │ │ ├── HomeFragment.kt │ │ │ └── HomeTestActivity.kt │ │ │ ├── viewmodel │ │ │ └── HomeViewModel.kt │ │ │ └── widget │ │ │ └── NSParentLayout2.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── drawable │ │ ├── shape_tag1.xml │ │ └── shape_tag2.xml │ │ ├── layout │ │ ├── activity_hometest.xml │ │ ├── fragment_home.xml │ │ ├── item_banner.xml │ │ └── item_home_rv.xml │ │ └── values │ │ ├── colors.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_home │ └── ExampleUnitTest.kt ├── kb_me ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_me │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_me │ │ │ ├── adapter │ │ │ ├── CollectItemClickListener.kt │ │ │ └── CollectRVAdapter.kt │ │ │ ├── api │ │ │ └── MeApi.kt │ │ │ ├── bean │ │ │ └── MyCollect.kt │ │ │ ├── di │ │ │ └── MeModule.kt │ │ │ ├── repo │ │ │ └── MeRepo.kt │ │ │ ├── ui │ │ │ └── MyCollectFragment.kt │ │ │ └── viewmodel │ │ │ └── MeViewModel.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── layout │ │ ├── fragment_collect.xml │ │ └── item_collect_rv.xml │ │ └── values │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_me │ └── ExampleUnitTest.kt ├── kb_navigation ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_navigation │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_navigation │ │ │ ├── adapter │ │ │ ├── NaviItemClickListener.kt │ │ │ ├── NaviItemEvent.kt │ │ │ ├── NaviRVAdapter.kt │ │ │ ├── NaviVPAdapter.kt │ │ │ └── SysRVAdapter.kt │ │ │ ├── api │ │ │ └── NaviApi.kt │ │ │ ├── bean │ │ │ ├── Navi.kt │ │ │ └── Sys.kt │ │ │ ├── di │ │ │ └── NaviModule.kt │ │ │ ├── repo │ │ │ └── NaviRepo.kt │ │ │ ├── ui │ │ │ ├── MainFragment.kt │ │ │ ├── NaviFragment.kt │ │ │ └── SysFragment.kt │ │ │ └── viewmodel │ │ │ └── NaviViewModel.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── layout │ │ ├── fragment_main.xml │ │ ├── fragment_sys.xml │ │ ├── item_flex.xml │ │ ├── item_sys.xml │ │ └── item_sys_rv.xml │ │ └── values │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_navigation │ └── ExampleUnitTest.kt ├── kb_project ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_project │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_project │ │ │ ├── adapter │ │ │ ├── ProItemClickListener.kt │ │ │ ├── ProRVAdapter.kt │ │ │ └── ProVPAdapter.kt │ │ │ ├── api │ │ │ └── ProjectApi.kt │ │ │ ├── bean │ │ │ ├── Project.kt │ │ │ └── ProjectType.kt │ │ │ ├── di │ │ │ └── ProjectModule.kt │ │ │ ├── repo │ │ │ └── ProjectRepo.kt │ │ │ ├── ui │ │ │ ├── ProjectChildFragment.kt │ │ │ └── ProjectFragment.kt │ │ │ └── viewmodel │ │ │ └── ProjectViewModel.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── layout │ │ ├── fragment_project.xml │ │ ├── fragment_project_child.xml │ │ └── item_pro_rv.xml │ │ └── values │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_project │ └── ExampleUnitTest.kt ├── kb_user ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_user │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_user │ │ │ ├── api │ │ │ └── UserApi.kt │ │ │ ├── bean │ │ │ └── LoginBean.kt │ │ │ ├── di │ │ │ └── UserModule.kt │ │ │ ├── repo │ │ │ └── LoginRepo.kt │ │ │ ├── ui │ │ │ └── LoginActivity.kt │ │ │ └── viewmodel │ │ │ └── LoginViewModel.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ ├── layout │ │ └── activity_login.xml │ │ └── values │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_user │ └── ExampleUnitTest.kt ├── kb_web ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── stew │ │ └── kb_web │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── stew │ │ │ └── kb_web │ │ │ └── ui │ │ │ └── WebActivity.kt │ ├── manifest │ │ └── AndroidManifest.xml │ └── res │ │ └── layout │ │ └── activity_web.xml │ └── test │ └── java │ └── com │ └── stew │ └── kb_web │ └── ExampleUnitTest.kt └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | /local.properties 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | app/release 18 | proguardMapping.txt 19 | app_plugin_repo 20 | app_plugin -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Android 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/ADActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox 2 | 3 | import android.content.Intent 4 | import android.graphics.Bitmap 5 | import android.util.Log 6 | import com.stew.kb_common.base.BaseActivity 7 | import com.stew.kotlinbox.databinding.ActivitySplashBinding 8 | 9 | /** 10 | * Created by stew on 4/21/22. 11 | * mail: stewforani@gmail.com 12 | */ 13 | class ADActivity : BaseActivity() { 14 | 15 | override fun getLayoutID(): Int { 16 | return R.layout.activity_splash 17 | } 18 | 19 | override fun init() { 20 | // val oldTime = System.currentTimeMillis() 21 | // Log.d("TAG", oldTime.toString()) 22 | Log.d(TAG, "App start") 23 | startActivity(Intent(this, MainActivity::class.java)) 24 | finish() 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/ATConstants.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | /** 4 | * Created by stew on 2024/6/26. 5 | * mail: stewforani@gmail.com 6 | */ 7 | class ATConstants { 8 | companion object{ 9 | const val TASK1 = "task1" 10 | const val TASK2 = "task2" 11 | const val TASK3 = "task3" 12 | const val TASK4 = "task4" 13 | const val TASK5 = "task5" 14 | const val TASK6 = "task6" 15 | const val TASK7 = "task7" 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/ApplicationAnchorTaskCreator.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.xj.anchortask.library.AnchorTask 4 | import com.xj.anchortask.library.IAnchorTaskCreator 5 | 6 | /** 7 | * Created by stew on 2024/6/26. 8 | * mail: stewforani@gmail.com 9 | */ 10 | class ApplicationAnchorTaskCreator : IAnchorTaskCreator { 11 | override fun createTask(taskName: String): AnchorTask? { 12 | when (taskName) { 13 | ATConstants.TASK1 -> { 14 | return Task1() 15 | } 16 | ATConstants.TASK2 -> { 17 | return Task2() 18 | } 19 | ATConstants.TASK3 -> { 20 | return Task3() 21 | } 22 | ATConstants.TASK4 -> { 23 | return Task4() 24 | } 25 | ATConstants.TASK5 -> { 26 | return Task5() 27 | } 28 | ATConstants.TASK6 -> { 29 | return Task6() 30 | } 31 | ATConstants.TASK7 -> { 32 | return Task7() 33 | } 34 | } 35 | return null 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task1.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.stew.kb_home.di.homeModule 4 | import com.stew.kb_me.di.meModule 5 | import com.stew.kb_navigation.di.naviModule 6 | import com.stew.kb_project.di.ProjectModule 7 | import com.stew.kb_user.di.userModule 8 | import com.stew.kotlinbox.KBApplication 9 | import com.xj.anchortask.library.AnchorTask 10 | import org.koin.android.ext.koin.androidContext 11 | import org.koin.android.ext.koin.androidLogger 12 | import org.koin.core.context.startKoin 13 | 14 | /** 15 | * Created by stew on 2024/6/26. 16 | * mail: stewforani@gmail.com 17 | */ 18 | class Task1 : AnchorTask(ATConstants.TASK1) { 19 | 20 | private val modules = mutableListOf(homeModule, ProjectModule, naviModule, meModule, userModule) 21 | 22 | override fun run() { 23 | startKoin { 24 | androidLogger() 25 | androidContext(KBApplication.instance!!) 26 | modules(modules) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task2.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.alibaba.android.arouter.launcher.ARouter 4 | import com.stew.kotlinbox.BuildConfig 5 | import com.stew.kotlinbox.KBApplication 6 | import com.xj.anchortask.library.AnchorTask 7 | 8 | /** 9 | * Created by stew on 2024/6/26. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class Task2 : AnchorTask(ATConstants.TASK2) { 13 | 14 | override fun run() { 15 | if (BuildConfig.DEBUG) { 16 | ARouter.openLog() 17 | ARouter.openDebug() 18 | } 19 | ARouter.init(KBApplication.instance) 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task3.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.stew.kotlinbox.KBApplication 4 | import com.tencent.mmkv.MMKV 5 | import com.xj.anchortask.library.AnchorTask 6 | 7 | /** 8 | * Created by stew on 2024/6/26. 9 | * mail: stewforani@gmail.com 10 | */ 11 | class Task3 : AnchorTask(ATConstants.TASK3) { 12 | 13 | override fun run() { 14 | MMKV.initialize(KBApplication.instance) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task4.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.stew.kb_common.util.AppLogUtil 4 | import com.stew.kotlinbox.KBApplication 5 | import com.xj.anchortask.library.AnchorTask 6 | 7 | /** 8 | * Created by stew on 2024/6/26. 9 | * mail: stewforani@gmail.com 10 | */ 11 | class Task4 : AnchorTask(ATConstants.TASK4) { 12 | 13 | override fun run() { 14 | AppLogUtil.init(KBApplication.instance!!) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task5.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import com.stew.kb_common.util.AppCommonUitl 4 | import com.stew.kotlinbox.KBApplication 5 | import com.xj.anchortask.library.AnchorTask 6 | 7 | /** 8 | * Created by stew on 2024/6/26. 9 | * mail: stewforani@gmail.com 10 | */ 11 | class Task5 : AnchorTask(ATConstants.TASK5) { 12 | override fun run() { 13 | AppCommonUitl.init(KBApplication.instance!!) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task6.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import androidx.appcompat.app.AppCompatDelegate 4 | import com.stew.kb_common.util.AppCommonUitl 5 | import com.stew.kb_common.util.Constants 6 | import com.stew.kb_common.util.KVUtil 7 | import com.xj.anchortask.library.AnchorTask 8 | 9 | /** 10 | * Created by stew on 2024/6/26. 11 | * mail: stewforani@gmail.com 12 | */ 13 | class Task6 : AnchorTask(ATConstants.TASK6) { 14 | override fun run() { 15 | when (val userDarkMode = KVUtil.getInt(Constants.USER_DARK_MODE, 999)) { 16 | 999 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 17 | 1000 -> AppCommonUitl.setFollowSystemTheme() 18 | else -> AppCompatDelegate.setDefaultNightMode(userDarkMode) 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/asyncthird/Task7.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.asyncthird 2 | 3 | import android.app.Activity 4 | import android.app.Application 5 | import android.os.Bundle 6 | import android.util.Log 7 | import com.stew.kotlinbox.KBApplication 8 | import com.xj.anchortask.library.AnchorTask 9 | 10 | /** 11 | * Created by stew on 2024/6/26. 12 | * mail: stewforani@gmail.com 13 | */ 14 | class Task7 : AnchorTask(ATConstants.TASK7) { 15 | override fun run() { 16 | KBApplication.instance!!.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { 17 | override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { 18 | Log.d(TAG, "onActivityCreated: " + activity.localClassName) 19 | } 20 | 21 | override fun onActivityStarted(activity: Activity) { 22 | Log.d(TAG, "onActivityStarted: " + activity.localClassName) 23 | } 24 | 25 | override fun onActivityResumed(activity: Activity) { 26 | Log.d(TAG, "onActivityResumed: " + activity.localClassName) 27 | } 28 | 29 | override fun onActivityPaused(activity: Activity) { 30 | Log.d(TAG, "onActivityPaused: " + activity.localClassName) 31 | } 32 | 33 | override fun onActivityStopped(activity: Activity) { 34 | Log.d(TAG, "onActivityStopped: " + activity.localClassName) 35 | } 36 | 37 | override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { 38 | Log.d(TAG, "onActivitySaveInstanceState: " + activity.localClassName) 39 | } 40 | 41 | override fun onActivityDestroyed(activity: Activity) { 42 | Log.d(TAG, "onActivityDestroyed: " + activity.localClassName) 43 | } 44 | 45 | }) 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/hooktest/HookClassLoader.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.hooktest 2 | 3 | import android.app.Application 4 | import dalvik.system.BaseDexClassLoader 5 | 6 | /** 7 | * Created by stew on 2023/7/20. 8 | * mail: stewforani@gmail.com 9 | */ 10 | object HookClassLoader { 11 | 12 | fun hook(app: Application) { 13 | 14 | val cl = app.classLoader 15 | val pcl = ProxyClassLoader("", cl.parent) 16 | 17 | val plf = BaseDexClassLoader::class.java.getDeclaredField("pathList") 18 | plf.isAccessible = true 19 | val pl = plf.get(cl) 20 | plf.set(pcl, pl) 21 | 22 | val parentF = ClassLoader::class.java.getDeclaredField("parent") 23 | parentF.isAccessible = true 24 | parentF.set(cl, pcl) 25 | 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/stew/kotlinbox/hooktest/ProxyClassLoader.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kotlinbox.hooktest 2 | 3 | import android.util.Log 4 | import dalvik.system.PathClassLoader 5 | 6 | /** 7 | * Created by stew on 2023/7/20. 8 | * mail: stewforani@gmail.com 9 | */ 10 | class ProxyClassLoader(dexPath: String, classLoader: ClassLoader) : 11 | PathClassLoader(dexPath, classLoader) { 12 | override fun loadClass(name: String?, resolve: Boolean): Class<*> { 13 | val begin = System.nanoTime() 14 | val clz = super.loadClass(name, resolve) 15 | val end = System.currentTimeMillis() 16 | Log.d( 17 | "ProxyClassLoader", 18 | "loadClass: " + clz.name + " / " + (end - begin) + "ms / " + Thread.currentThread().id 19 | ) 20 | return clz 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_main_pop.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 21 | 22 | 28 | 29 | 30 | 31 | 35 | 36 | 43 | 44 | 49 | 50 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main_bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-ldpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-ldpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | KotlinBox 3 | Home 4 | Project 5 | Navigation 6 | Collect 7 | Experiment 8 | DarkMode 9 | SwitchTheme 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app_plugin/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.kotlin.jvm' 3 | id 'java-gradle-plugin' 4 | id 'maven-publish' 5 | } 6 | 7 | java { 8 | withJavadocJar() 9 | withSourcesJar() 10 | } 11 | 12 | publishing { 13 | publications { 14 | mavenJava(MavenPublication) { 15 | groupId "io.github.stewforani" 16 | artifactId "methodtime" 17 | version "1.0.0" 18 | from components.java 19 | } 20 | } 21 | repositories { 22 | maven { 23 | url "../app_plugin_repo" 24 | } 25 | } 26 | } 27 | gradlePlugin { 28 | plugins { 29 | MethodTimePlugin { 30 | id = 'MethodTimePlugin' 31 | implementationClass = 'com.stew.app_plugin.AppPlugin' 32 | } 33 | } 34 | } 35 | 36 | dependencies { 37 | implementation 'com.android.tools.build:gradle:7.4.2' 38 | implementation 'org.ow2.asm:asm:9.2' 39 | implementation 'org.ow2.asm:asm-commons:9.2' 40 | } 41 | -------------------------------------------------------------------------------- /app_plugin/src/main/java/com/stew/app_plugin/AppPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.stew.app_plugin 2 | 3 | import com.android.build.api.instrumentation.FramesComputationMode 4 | import com.android.build.api.instrumentation.InstrumentationScope 5 | import com.android.build.api.variant.AndroidComponentsExtension 6 | import org.gradle.api.Plugin 7 | import org.gradle.api.Project 8 | 9 | class AppPlugin :Plugin{ 10 | override fun apply(p0: Project) { 11 | println(" **** AppPlugin start : "+p0.name+" **** ") 12 | val ex = p0.extensions.getByType(AndroidComponentsExtension::class.java) 13 | ex.onVariants { 14 | it.instrumentation.transformClassesWith(MTTransform::class.java,InstrumentationScope.PROJECT) {} 15 | it.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS) 16 | } 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /app_plugin/src/main/java/com/stew/app_plugin/MTTransform.kt: -------------------------------------------------------------------------------- 1 | package com.stew.app_plugin 2 | 3 | import com.android.build.api.instrumentation.AsmClassVisitorFactory 4 | import com.android.build.api.instrumentation.ClassContext 5 | import com.android.build.api.instrumentation.ClassData 6 | import com.android.build.api.instrumentation.InstrumentationParameters 7 | import org.objectweb.asm.ClassVisitor 8 | import org.objectweb.asm.MethodVisitor 9 | import org.objectweb.asm.Opcodes 10 | 11 | /** 12 | * Created by stew on 2023/6/8. 13 | * mail: stewforani@gmail.com 14 | */ 15 | abstract class MTTransform : AsmClassVisitorFactory { 16 | override fun createClassVisitor( 17 | classContext: ClassContext, 18 | nextClassVisitor: ClassVisitor 19 | ): ClassVisitor { 20 | return object : ClassVisitor(Opcodes.ASM5, nextClassVisitor) { 21 | val cName = classContext.currentClassData.className 22 | 23 | override fun visit( 24 | version: Int, 25 | access: Int, 26 | name: String?, 27 | signature: String?, 28 | superName: String?, 29 | interfaces: Array? 30 | ) { 31 | super.visit(version, access, name, signature, superName, interfaces) 32 | if (classFilter(cName)) { 33 | println("---classname = $cName") 34 | } 35 | } 36 | 37 | override fun visitMethod( 38 | access: Int, 39 | name: String?, 40 | descriptor: String?, 41 | signature: String?, 42 | exceptions: Array? 43 | ): MethodVisitor { 44 | val mv = super.visitMethod(access, name, descriptor, signature, exceptions) 45 | if (classFilter(cName) && methodFilter(name!!)) { 46 | println("***method = $name") 47 | return MTMethodVisitor(cName, mv, access, name, descriptor) 48 | } 49 | return mv 50 | } 51 | } 52 | } 53 | 54 | override fun isInstrumentable(classData: ClassData): Boolean { 55 | return true 56 | } 57 | 58 | fun classFilter(cName: String): Boolean { 59 | return !cName.contains("Base") && (cName.endsWith("Activity") || cName.endsWith("Fragment")) 60 | } 61 | 62 | fun methodFilter(mName: String): Boolean { 63 | return !mName.contains("$") && !mName.contains("") 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = "1.7.20" 5 | repositories { 6 | google() 7 | mavenCentral() 8 | // maven { url 'app_plugin_repo' } 9 | } 10 | 11 | dependencies { 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | classpath 'com.android.tools.build:gradle:7.4.2' 14 | 15 | // classpath 'io.github.stewforani:methodtime:1.0.0' 16 | // classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.18' 17 | //NOTE: Do not place your application dependencies here; they belong 18 | //in the individual module build.gradle.kts files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | google() 25 | mavenCentral() 26 | maven { url 'https://www.jitpack.io' } 27 | } 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } -------------------------------------------------------------------------------- /github_imgs/w1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w1.jpeg -------------------------------------------------------------------------------- /github_imgs/w2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w2.jpeg -------------------------------------------------------------------------------- /github_imgs/w3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w3.jpeg -------------------------------------------------------------------------------- /github_imgs/w4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w4.jpeg -------------------------------------------------------------------------------- /github_imgs/w5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w5.jpeg -------------------------------------------------------------------------------- /github_imgs/w6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/github_imgs/w6.jpeg -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | 23 | singleModule=false 24 | org.gradle.unsafe.configuration-cache=true 25 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jun 06 13:16:01 CST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /kb_common/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_common/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply from: '../dependencies.gradle' 3 | 4 | dependencies { 5 | //oKHttp 6 | implementation("com.squareup.okhttp3:okhttp:4.9.0") 7 | implementation("com.squareup.okhttp3:logging-interceptor:4.9.0") 8 | //retrofit 9 | api("com.squareup.retrofit2:retrofit:2.9.0") 10 | implementation("com.squareup.retrofit2:converter-gson:2.9.0") 11 | } -------------------------------------------------------------------------------- /kb_common/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/consumer-rules.pro -------------------------------------------------------------------------------- /kb_common/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_common/src/androidTest/java/com/stew/kb_common/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_common.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/base/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.base 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import androidx.databinding.DataBindingUtil 10 | import androidx.databinding.ViewDataBinding 11 | import androidx.fragment.app.Fragment 12 | import com.stew.kb_common.util.LoadingViewUtil 13 | 14 | /** 15 | * Created by stew on 4/22/22. 16 | * mail: stewforani@gmail.com 17 | */ 18 | abstract class BaseFragment : Fragment() { 19 | 20 | val TAG: String = this.javaClass.simpleName 21 | lateinit var mBind: T 22 | lateinit var mContext: Context 23 | 24 | override fun onAttach(context: Context) { 25 | super.onAttach(context) 26 | mContext = context 27 | } 28 | 29 | abstract fun getLayoutID(): Int 30 | 31 | override fun onCreateView( 32 | inflater: LayoutInflater, 33 | container: ViewGroup?, 34 | savedInstanceState: Bundle? 35 | ): View? { 36 | Log.d(TAG, "onCreateView: ") 37 | mBind = DataBindingUtil.inflate(inflater, getLayoutID(), container, false) 38 | return mBind.root 39 | } 40 | 41 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 42 | super.onViewCreated(view, savedInstanceState) 43 | Log.d(TAG, "onViewCreated: ") 44 | } 45 | 46 | override fun onStart() { 47 | super.onStart() 48 | Log.d(TAG, "onStart: ") 49 | } 50 | 51 | override fun onResume() { 52 | super.onResume() 53 | Log.d(TAG, "onResume: ") 54 | } 55 | 56 | override fun onPause() { 57 | super.onPause() 58 | Log.d(TAG, "onPause: ") 59 | } 60 | 61 | override fun onStop() { 62 | super.onStop() 63 | Log.d(TAG, "onStop: ") 64 | } 65 | 66 | override fun onDestroyView() { 67 | super.onDestroyView() 68 | Log.d(TAG, "onDestroyView: ") 69 | } 70 | 71 | override fun onDestroy() { 72 | super.onDestroy() 73 | Log.d(TAG, "onDestroy: ") 74 | mBind.unbind() 75 | } 76 | 77 | fun showLoadingDialog() { 78 | Log.d(TAG, TAG + "showLoadingDialog: ") 79 | LoadingViewUtil.showLoadingDialog(mContext, true) 80 | } 81 | 82 | fun dismissLoadingDialog() { 83 | Log.d(TAG, TAG + "dismissLoadingDialog: ") 84 | LoadingViewUtil.dismissLoadingDialog() 85 | } 86 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/base/BaseVMFragment.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.base 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.View 7 | import androidx.databinding.ViewDataBinding 8 | import com.stew.kb_common.util.LoadingViewUtil 9 | 10 | /** 11 | * Created by stew on 7/30/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | abstract class BaseVMFragment : BaseFragment() { 15 | protected var currentPage = 0 16 | protected var currentPageSize = 10 17 | private var isFirstLoad: Boolean = true 18 | 19 | abstract fun observe() 20 | abstract fun init() 21 | 22 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 23 | super.onViewCreated(view, savedInstanceState) 24 | observe() 25 | init() 26 | } 27 | 28 | override fun onResume() { 29 | super.onResume() 30 | if (isFirstLoad) { 31 | isFirstLoad = false 32 | lazyLoad() 33 | } 34 | } 35 | 36 | open fun lazyLoad() {} 37 | 38 | open fun resetState() {} 39 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/base/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.base 2 | 3 | import android.util.Log 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.viewModelScope 6 | import kotlinx.coroutines.launch 7 | 8 | /** 9 | * Created by stew on 7/29/22. 10 | * mail: stewforani@gmail.com 11 | */ 12 | 13 | typealias vmBLOCK = suspend () -> Unit 14 | 15 | open class BaseViewModel : ViewModel() { 16 | 17 | //fun 默认public,这里使用protected 18 | protected fun launch( 19 | block: vmBLOCK 20 | ) { 21 | //使用viewModelScope需要添加依赖androidx.navigation:navigation-fragment-ktx 22 | //这里不需要指定viewModelScope.launch(Dispatchers.IO),因为retrofit自身会在子线程进行网络请求 23 | viewModelScope.launch { 24 | try { 25 | block.invoke() 26 | } catch (e: Exception) { 27 | onError(e) 28 | } 29 | } 30 | } 31 | 32 | private fun onError(e: Exception) { 33 | Log.d("onError", "onError: $e") 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/base/FlowBaseRepository.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.base 2 | 3 | /** 4 | * Created by stew on 2023/8/2. 5 | * mail: stewforani@gmail.com 6 | */ 7 | open class FlowBaseRepository { 8 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/BaseResp.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | /** 4 | * Created by stew on 6/12/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | class BaseResp { 8 | var errorCode: Int = -1 9 | var errorMsg: String = "" 10 | var data: T? = null 11 | var responseState: ResponseState? = null 12 | enum class ResponseState { 13 | REQUEST_START, 14 | REQUEST_SUCCESS, 15 | REQUEST_FAILED, 16 | REQUEST_ERROR 17 | } 18 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/BaseStateObserver.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | import android.util.Log 4 | import androidx.lifecycle.Observer 5 | 6 | /** 7 | * Created by stew on 8/28/22. 8 | * mail: stewforani@gmail.com 9 | */ 10 | open class BaseStateObserver(var t: Boolean?) : Observer> { 11 | 12 | override fun onChanged(value: BaseResp) { 13 | 14 | when (value.responseState) { 15 | BaseResp.ResponseState.REQUEST_START -> { 16 | Log.d("BaseStateObserver", "Observer: start") 17 | getRespDataStart() 18 | } 19 | BaseResp.ResponseState.REQUEST_SUCCESS -> { 20 | Log.d("BaseStateObserver", "Observer: success") 21 | if(value.data==null){ 22 | getRespSuccess() 23 | }else{ 24 | getRespDataSuccess(value.data!!) 25 | } 26 | 27 | } 28 | BaseResp.ResponseState.REQUEST_FAILED -> { 29 | Log.d("BaseStateObserver", "Observer: failed") 30 | getRespDataEnd() 31 | } 32 | BaseResp.ResponseState.REQUEST_ERROR -> { 33 | Log.d("BaseStateObserver", "Observer: error") 34 | getRespDataEnd() 35 | } 36 | 37 | else -> {} 38 | } 39 | } 40 | 41 | open fun getRespDataStart() {} 42 | open fun getRespDataSuccess(it: T) {} 43 | open fun getRespSuccess() {} 44 | open fun getRespDataEnd() {} 45 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/CookieBean.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | import okhttp3.Cookie 4 | 5 | /** 6 | * Created by stew on 8/23/22. 7 | * mail: stewforani@gmail.com 8 | */ 9 | data class CookieBean ( 10 | val list: List 11 | ) 12 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/MyCookieJar.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | import android.util.Log 4 | import com.google.gson.Gson 5 | import com.stew.kb_common.util.Constants 6 | import com.stew.kb_common.util.KVUtil 7 | import okhttp3.Cookie 8 | import okhttp3.CookieJar 9 | import okhttp3.HttpUrl 10 | 11 | /** 12 | * Created by stew on 8/21/22. 13 | * mail: stewforani@gmail.com 14 | */ 15 | class MyCookieJar : CookieJar { 16 | 17 | private val gson = Gson() 18 | 19 | override fun loadForRequest(url: HttpUrl): List { 20 | val s = KVUtil.getString(Constants.USER_COOKIE) 21 | if (s != null) { 22 | val l = gson.fromJson(s, CookieBean::class.java).list 23 | Log.d("OkHttp", "loadForRequest: $l") 24 | return l 25 | } 26 | return arrayListOf() 27 | } 28 | 29 | override fun saveFromResponse(url: HttpUrl, cookies: List) { 30 | Log.d("OkHttp", "saveFromResponse:1") 31 | 32 | if (KVUtil.getString(Constants.USER_COOKIE) != null) { 33 | Log.d("OkHttp", "saveFromResponse:2") 34 | return 35 | } 36 | 37 | for (item in cookies) { 38 | if (item.toString().contains("loginUserName")) { 39 | Log.d("OkHttp", "saveFromResponse:3") 40 | KVUtil.put(Constants.USER_COOKIE, gson.toJson(CookieBean(list = cookies))) 41 | break 42 | } 43 | } 44 | 45 | 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/RespStateData.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | /** 6 | * Created by stew on 8/28/22. 7 | * mail: stewforani@gmail.com 8 | */ 9 | class RespStateData : MutableLiveData>() -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/network/RetrofitManager.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.network 2 | 3 | import android.util.Log 4 | import okhttp3.OkHttpClient 5 | import okhttp3.logging.HttpLoggingInterceptor 6 | import retrofit2.Retrofit 7 | import retrofit2.converter.gson.GsonConverterFactory 8 | import java.util.concurrent.TimeUnit 9 | 10 | /** 11 | * Created by stew on 5/20/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | object RetrofitManager { 15 | 16 | private const val BASE_URL = "https://www.wanandroid.com/" 17 | 18 | private var retrofit: Retrofit 19 | 20 | init { 21 | 22 | val logInterceptor = HttpLoggingInterceptor { 23 | Log.d("OkHttp Log : ", it) 24 | }.setLevel(HttpLoggingInterceptor.Level.BODY) 25 | 26 | val okHttpClient = OkHttpClient().newBuilder() 27 | .callTimeout(10, TimeUnit.SECONDS) 28 | .connectTimeout(10, TimeUnit.SECONDS) 29 | .readTimeout(10, TimeUnit.SECONDS) 30 | .writeTimeout(10, TimeUnit.SECONDS) 31 | .retryOnConnectionFailure(true) 32 | .followRedirects(false) 33 | .cookieJar(MyCookieJar()) 34 | .addInterceptor(logInterceptor) 35 | .build() 36 | 37 | retrofit = Retrofit.Builder() 38 | .client(okHttpClient) 39 | .baseUrl(BASE_URL) 40 | .addConverterFactory(GsonConverterFactory.create()) 41 | .build() 42 | 43 | } 44 | 45 | fun getService(service: Class): T { 46 | return retrofit.create(service) 47 | } 48 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/AppLogUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | import android.app.Application 4 | import android.util.Log 5 | import okio.BufferedSink 6 | import okio.Sink 7 | import okio.appendingSink 8 | import okio.buffer 9 | import java.io.File 10 | import java.util.concurrent.Executors 11 | 12 | /** 13 | * Created by stew on 2023/5/16. 14 | * mail: stewforani@gmail.com 15 | */ 16 | object AppLogUtil { 17 | private var mContext: Application? = null 18 | private var logFile: File? = null 19 | private var sink: Sink? = null 20 | private var bufferedSink: BufferedSink? = null 21 | private val logThread = Executors.newFixedThreadPool(1) 22 | 23 | private fun runOnWorkerThread(runnable: Runnable?) { 24 | logThread.execute(runnable) 25 | } 26 | 27 | fun init(context: Application) { 28 | mContext = context 29 | } 30 | 31 | fun addLifeLog(data: String?) { 32 | runOnWorkerThread(Runnable { 33 | try { 34 | Log.d("addLifeLog", "addLifeLog: 1") 35 | val path = mContext!!.getExternalFilesDir(null).toString() + "/logs/" 36 | if (logFile == null) { 37 | logFile = File(path, "lifelog.txt") 38 | } 39 | if (!logFile!!.exists()) { 40 | Log.d("addLifeLog", "addLifeLog: 2") 41 | val dir = File(path) 42 | if (dir.mkdirs()) { 43 | if (logFile!!.createNewFile()) { 44 | Log.d("addLifeLog", "addLifeLog: 3") 45 | } 46 | } 47 | } 48 | Log.d("addLifeLog", "addLifeLog: 4") 49 | sink = logFile!!.appendingSink() 50 | bufferedSink = sink!!.buffer() 51 | bufferedSink!!.writeUtf8(System.currentTimeMillis().toString()) 52 | bufferedSink!!.writeUtf8(" ----- ") 53 | bufferedSink!!.writeUtf8(data!!) 54 | bufferedSink!!.writeUtf8("\n") 55 | bufferedSink!!.flush() 56 | sink!!.close() 57 | } catch (e: Exception) { 58 | throw RuntimeException(e) 59 | } 60 | }) 61 | } 62 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | /** 4 | * Created by stew on 8/18/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | class Constants { 8 | companion object { 9 | 10 | const val MIN_CLICK_DELAY_TIME: Int = 1000 11 | 12 | //arouter 13 | const val WEB_TITLE: String = "web_title" 14 | const val WEB_LINK: String = "web_link" 15 | 16 | const val PATH_EXP: String = "/kotlinbox/ExpActivity" 17 | const val PATH_NH: String = "/kotlinbox/exp/NativeHookActivity" 18 | const val PATH_PI: String = "/kotlinbox/exp/ProcessInfoActivity" 19 | const val PATH_DP: String = "/kotlinbox/exp/DpActivity" 20 | const val PATH_TP: String = "/kotlinbox/exp/TestPluginApkActivity" 21 | const val PATH_DS: String = "/kotlinbox/exp/DsActivity" 22 | const val PATH_DM: String = "/kotlinbox/exp/DmActivity" 23 | const val PATH_APP: String = "/kotlinbox/exp/RestartAppActivity" 24 | const val PATH_PICK_IMAGE: String = "/kotlinbox/exp/PickImageActivity" 25 | 26 | const val PATH_WEB: String = "/kb_web/ui/WebActivity" 27 | const val PATH_LOGIN: String = "/kb_user/ui/LoginActivity" 28 | 29 | //kv 30 | const val USER_NAME: String = "user_name" 31 | const val USER_COOKIE: String = "user_cookie" 32 | const val USER_DARK_MODE: String = "user_dark_mode" 33 | 34 | //http 35 | const val HTTP_SUCCESS = 0 36 | const val HTTP_AUTH_INVALID = -1001 37 | 38 | //dynamic load so 39 | var isSoLoad = false 40 | var isStartDP = false 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/Extension.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | import android.content.res.Resources 4 | 5 | /** 6 | * Created by stew on 8/24/22. 7 | * mail: stewforani@gmail.com 8 | */ 9 | object Extension { 10 | fun Number.px2dp(): Float { 11 | val f = toFloat() 12 | val scale: Float = Resources.getSystem().displayMetrics.density 13 | return (f / scale + 0.5f) 14 | } 15 | 16 | fun Number.dp2px(): Int { 17 | val f = toFloat() 18 | val scale: Float = Resources.getSystem().displayMetrics.density 19 | return (f * scale + 0.5f).toInt() 20 | } 21 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/KVUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | import android.os.Parcelable 4 | import com.tencent.mmkv.MMKV 5 | 6 | /** 7 | * Created by stew on 8/21/22. 8 | * mail: stewforani@gmail.com 9 | */ 10 | object KVUtil { 11 | 12 | var kv = MMKV.defaultMMKV() 13 | 14 | fun put(key: String, value: Any?) { 15 | when (value) { 16 | is Boolean -> kv.putBoolean(key, value) 17 | is ByteArray -> kv.putBytes(key, value) 18 | is Float -> kv.putFloat(key, value) 19 | is Int -> kv.putInt(key, value) 20 | is Long -> kv.putLong(key, value) 21 | is String -> kv.putString(key, value) 22 | } 23 | } 24 | 25 | fun getBoolean(key: String, defValue: Boolean = false) = kv.getBoolean(key, defValue) 26 | 27 | fun getBytes(key: String, defValue: ByteArray? = null) = kv.getBytes(key, defValue) 28 | 29 | fun getFloat(key: String, defValue: Float = 0f) = kv.getFloat(key, defValue) 30 | 31 | fun getInt(key: String, defValue: Int = 0) = kv.getInt(key, defValue) 32 | 33 | fun getLong(key: String, defValue: Long = 0L) = kv.getLong(key, defValue) 34 | 35 | fun getString(key: String, defValue: String? = null) = kv.getString(key, defValue) 36 | 37 | fun remove(key: String) = kv.remove(key) 38 | 39 | //------------------------------------------------------------------------ 40 | 41 | fun putParcelable(key: String, t: T): Boolean { 42 | return kv.encode(key, t) 43 | } 44 | 45 | inline fun getParcelable(key: String): T? { 46 | return kv.decodeParcelable(key, T::class.java) 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/LoadingViewUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.graphics.Color 6 | import android.graphics.drawable.ColorDrawable 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import androidx.appcompat.app.AlertDialog 10 | import com.stew.kb_common.R 11 | 12 | /** 13 | * Created by stew on 4/20/22. 14 | * mail: stewforani@gmail.com 15 | */ 16 | object LoadingViewUtil { 17 | 18 | private var dialog: AlertDialog? = null 19 | 20 | fun showLoadingDialog(context: Context, isCancel: Boolean) { 21 | 22 | if (context is Activity) { 23 | if (context.isFinishing) { 24 | return 25 | } 26 | } 27 | 28 | if (dialog == null) { 29 | val b = AlertDialog.Builder(context) 30 | b.setView( 31 | LayoutInflater.from(context).inflate(R.layout.common_loading_dialog, null) 32 | ) 33 | 34 | b.setCancelable(isCancel) 35 | dialog = b.create() 36 | 37 | if (dialog?.window == null) { 38 | return 39 | } 40 | 41 | dialog?.window?.setBackgroundDrawable(ColorDrawable(0)) 42 | } 43 | 44 | if (dialog != null && !(dialog!!.isShowing)) { 45 | dialog!!.show() 46 | } 47 | 48 | } 49 | 50 | fun dismissLoadingDialog() { 51 | if (dialog != null && dialog!!.isShowing) { 52 | dialog?.dismiss() 53 | dialog = null 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/StatusBarUtil.kt: -------------------------------------------------------------------------------- 1 | //package com.stew.kb_common.util 2 | // 3 | //import android.app.Activity 4 | //import android.graphics.Color 5 | //import android.os.Build 6 | //import android.view.View 7 | //import android.view.WindowManager 8 | // 9 | ///** 10 | // * Created by stew on 4/21/22. 11 | // * mail: stewforani@gmail.com 12 | // */ 13 | //object StatusBarUtil { 14 | // /** 15 | // * 6.0级以上的沉浸式布局 16 | // * 17 | // * @param activity 18 | // */ 19 | // fun fitSystemBar(activity: Activity) { 20 | // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 21 | // return 22 | // } 23 | // val window = activity.window 24 | // val decorView = window.decorView 25 | // //View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN--能够使得我们的页面布局延伸到状态栏之下,但不会隐藏状态栏。也就相当于状态栏是遮盖在布局之上的 26 | // //View.SYSTEM_UI_FLAG_FULLSCREEN -- 能够使得我们的页面布局延伸到状态栏,但是会隐藏状态栏。 27 | // //WindowManager.LayoutParams.FLAG_FULLSCREEN 28 | // decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 29 | // or View.SYSTEM_UI_FLAG_LAYOUT_STABLE 30 | // or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) 31 | // window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) 32 | // window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) 33 | // window.statusBarColor = Color.TRANSPARENT 34 | // } 35 | // 36 | // /** 37 | // * 6.0及以上的状态栏色调 38 | // * 39 | // * @param activity 40 | // * @param light true:白底黑字,false:黑底白字 41 | // */ 42 | // fun lightStatusBar(activity: Activity, light: Boolean) { 43 | // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 44 | // return 45 | // } 46 | // val window = activity.window 47 | // val decorView = window.decorView 48 | // var visibility = decorView.systemUiVisibility 49 | // visibility = if (light) { 50 | // visibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 51 | // } else { 52 | // visibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() 53 | // } 54 | // decorView.systemUiVisibility = visibility 55 | // } 56 | //} -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/ToastUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util 2 | 3 | import android.app.Application 4 | import android.widget.Toast 5 | 6 | /** 7 | * Created by stew on 7/27/22. 8 | * mail: stewforani@gmail.com 9 | */ 10 | object ToastUtil { 11 | lateinit var mContext:Application 12 | fun init(context: Application){ 13 | mContext= context 14 | } 15 | 16 | fun showMsg(str:String){ 17 | Toast.makeText(mContext,str,Toast.LENGTH_SHORT).show() 18 | } 19 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/DSLoadUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.util.dynamic_loadso 2 | 3 | import android.util.Log 4 | import com.stew.kb_common.util.dynamic_loadso.elf.ElfParser 5 | import java.io.File 6 | 7 | /** 8 | * Created by stew on 2024/1/5. 9 | * mail: stewforani@gmail.com 10 | */ 11 | object DSLoadUtil { 12 | fun init(cl: ClassLoader, f: File) { 13 | 14 | try { 15 | LoadLibraryUtils.installNativeLibraryPath(cl, f) 16 | } catch (e: Exception) { 17 | e.printStackTrace() 18 | } 19 | 20 | } 21 | 22 | fun dsLoad(soPath: String, soFile: File) { 23 | var parse: ElfParser? = null 24 | var dp: MutableList? = null 25 | try { 26 | parse = ElfParser(soFile) 27 | dp = parse.parseNeededDependencies() 28 | Log.d("DSLoadUtil", "dsLoad: $dp") 29 | } finally { 30 | parse?.close() 31 | } 32 | 33 | if (dp != null) { 34 | for (d in dp) { 35 | val name = soPath + d 36 | val file = File(name) 37 | if (file.exists()) { 38 | //递归寻找依赖so 39 | dsLoad(soPath, file) 40 | } else { 41 | //非目录内,加载内置原生so 42 | System.loadLibrary(d.substring(3, d.length - 3)) 43 | } 44 | } 45 | } 46 | 47 | //加载当前so 48 | System.loadLibrary(soFile.name.substring(3, soFile.name.length - 3)) 49 | } 50 | } -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Dynamic32Structure.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | import java.io.IOException; 19 | import java.nio.ByteBuffer; 20 | import java.nio.ByteOrder; 21 | 22 | public class Dynamic32Structure extends Elf.DynamicStructure { 23 | public Dynamic32Structure(final ElfParser parser, final Elf.Header header, 24 | long baseOffset, final int index) throws IOException { 25 | final ByteBuffer buffer = ByteBuffer.allocate(4); 26 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 27 | 28 | baseOffset = baseOffset + (index * 8); 29 | tag = parser.readWord(buffer, baseOffset); 30 | val = parser.readWord(buffer, baseOffset + 0x4); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Dynamic64Structure.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Dynamic64Structure extends Elf.DynamicStructure { 24 | public Dynamic64Structure(final ElfParser parser, final Elf.Header header, 25 | long baseOffset, final int index) throws IOException { 26 | final ByteBuffer buffer = ByteBuffer.allocate(8); 27 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 28 | 29 | baseOffset = baseOffset + (index * 16); 30 | tag = parser.readLong(buffer, baseOffset); 31 | val = parser.readLong(buffer, baseOffset + 0x8); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Elf.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | import java.io.IOException; 19 | 20 | public interface Elf { 21 | abstract class Header { 22 | public static final int ELFCLASS32 = 1; // 32 Bit ELF 23 | public static final int ELFCLASS64 = 2; // 64 Bit ELF 24 | public static final int ELFDATA2MSB = 2; // Big Endian, 2s complement 25 | 26 | public boolean bigEndian; 27 | public int type; 28 | public long phoff; 29 | public long shoff; 30 | public int phentsize; 31 | public int phnum; 32 | public int shentsize; 33 | public int shnum; 34 | public int shstrndx; 35 | 36 | abstract public SectionHeader getSectionHeader(int index) throws IOException; 37 | abstract public ProgramHeader getProgramHeader(long index) throws IOException; 38 | abstract public DynamicStructure getDynamicStructure(long baseOffset, int index) 39 | throws IOException; 40 | } 41 | 42 | abstract class ProgramHeader { 43 | public static final int PT_LOAD = 1; // Loadable segment 44 | public static final int PT_DYNAMIC = 2; // Dynamic linking information 45 | 46 | public long type; 47 | public long offset; 48 | public long vaddr; 49 | public long memsz; 50 | } 51 | 52 | abstract class SectionHeader { 53 | public long info; 54 | } 55 | 56 | abstract class DynamicStructure { 57 | public static final int DT_NULL = 0; // Marks end of structure list 58 | public static final int DT_NEEDED = 1; // Needed library 59 | public static final int DT_STRTAB = 5; // String table 60 | 61 | public long tag; 62 | public long val; // Union with d_ptr 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Elf32Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | 20 | import java.io.IOException; 21 | import java.nio.ByteBuffer; 22 | import java.nio.ByteOrder; 23 | 24 | public class Elf32Header extends Elf.Header { 25 | private final ElfParser parser; 26 | 27 | public Elf32Header(final boolean bigEndian, final ElfParser parser) throws IOException { 28 | this.bigEndian = bigEndian; 29 | this.parser = parser; 30 | 31 | final ByteBuffer buffer = ByteBuffer.allocate(4); 32 | buffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 33 | 34 | type = parser.readHalf(buffer, 0x10); 35 | phoff = parser.readWord(buffer, 0x1C); 36 | shoff = parser.readWord(buffer, 0x20); 37 | phentsize = parser.readHalf(buffer, 0x2A); 38 | phnum = parser.readHalf(buffer, 0x2C); 39 | shentsize = parser.readHalf(buffer, 0x2E); 40 | shnum = parser.readHalf(buffer, 0x30); 41 | shstrndx = parser.readHalf(buffer, 0x32); 42 | } 43 | 44 | @Override 45 | public Elf.SectionHeader getSectionHeader(final int index) throws IOException { 46 | return new Section32Header(parser, this, index); 47 | } 48 | 49 | @Override 50 | public Elf.ProgramHeader getProgramHeader(final long index) throws IOException { 51 | return new Program32Header(parser, this, index); 52 | } 53 | 54 | @Override 55 | public Elf.DynamicStructure getDynamicStructure(final long baseOffset, final int index) 56 | throws IOException { 57 | return new Dynamic32Structure(parser, this, baseOffset, index); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Elf64Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Elf64Header extends Elf.Header { 24 | private final ElfParser parser; 25 | 26 | public Elf64Header(final boolean bigEndian, final ElfParser parser) throws IOException { 27 | this.bigEndian = bigEndian; 28 | this.parser = parser; 29 | 30 | final ByteBuffer buffer = ByteBuffer.allocate(8); 31 | buffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 32 | 33 | type = parser.readHalf(buffer, 0x10); 34 | phoff = parser.readLong(buffer, 0x20); 35 | shoff = parser.readLong(buffer, 0x28); 36 | phentsize = parser.readHalf(buffer, 0x36); 37 | phnum = parser.readHalf(buffer, 0x38); 38 | shentsize = parser.readHalf(buffer, 0x3A); 39 | shnum = parser.readHalf(buffer, 0x3C); 40 | shstrndx = parser.readHalf(buffer, 0x3E); 41 | } 42 | 43 | @Override 44 | public Elf.SectionHeader getSectionHeader(final int index) throws IOException { 45 | return new Section64Header(parser, this, index); 46 | } 47 | 48 | @Override 49 | public Elf.ProgramHeader getProgramHeader(final long index) throws IOException { 50 | return new Program64Header(parser, this, index); 51 | } 52 | 53 | @Override 54 | public Elf.DynamicStructure getDynamicStructure(final long baseOffset, final int index) 55 | throws IOException { 56 | return new Dynamic64Structure(parser, this, baseOffset, index); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Program32Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Program32Header extends Elf.ProgramHeader { 24 | public Program32Header(final ElfParser parser, final Elf.Header header, final long index) 25 | throws IOException { 26 | final ByteBuffer buffer = ByteBuffer.allocate(4); 27 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 28 | 29 | final long baseOffset = header.phoff + (index * header.phentsize); 30 | type = parser.readWord(buffer, baseOffset); 31 | offset = parser.readWord(buffer, baseOffset + 0x4); 32 | vaddr = parser.readWord(buffer, baseOffset + 0x8); 33 | memsz = parser.readWord(buffer, baseOffset + 0x14); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Program64Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Program64Header extends Elf.ProgramHeader { 24 | public Program64Header(final ElfParser parser, final Elf.Header header, final long index) 25 | throws IOException { 26 | final ByteBuffer buffer = ByteBuffer.allocate(8); 27 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 28 | 29 | final long baseOffset = header.phoff + (index * header.phentsize); 30 | type = parser.readWord(buffer, baseOffset); 31 | offset = parser.readLong(buffer, baseOffset + 0x8); 32 | vaddr = parser.readLong(buffer, baseOffset + 0x10); 33 | memsz = parser.readLong(buffer, baseOffset + 0x28); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Section32Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Section32Header extends Elf.SectionHeader { 24 | public Section32Header(final ElfParser parser, final Elf.Header header, final int index) 25 | throws IOException { 26 | final ByteBuffer buffer = ByteBuffer.allocate(4); 27 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 28 | 29 | info = parser.readWord(buffer, header.shoff + (index * header.shentsize) + 0x1C); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/util/dynamic_loadso/elf/Section64Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 - 2016 KeepSafe Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.stew.kb_common.util.dynamic_loadso.elf; 17 | 18 | 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | public class Section64Header extends Elf.SectionHeader { 24 | public Section64Header(final ElfParser parser, final Elf.Header header, final int index) 25 | throws IOException { 26 | final ByteBuffer buffer = ByteBuffer.allocate(8); 27 | buffer.order(header.bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); 28 | 29 | info = parser.readWord(buffer, header.shoff + (index * header.shentsize) + 0x2C); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kb_common/src/main/java/com/stew/kb_common/widget/MySwipeRefreshLayout.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout 7 | import com.stew.kb_common.util.Extension.dp2px 8 | import kotlin.math.abs 9 | 10 | /** 11 | * Created by stew on 8/23/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | class MySwipeRefreshLayout(context: Context, attr: AttributeSet) : 15 | SwipeRefreshLayout(context, attr) { 16 | 17 | var vpIsDragging: Boolean = false 18 | var x1 = 0f 19 | var y1 = 0f 20 | var x2 = 0f 21 | var y2 = 0f 22 | 23 | override fun onInterceptTouchEvent(event: MotionEvent?): Boolean { 24 | 25 | when (event?.action) { 26 | MotionEvent.ACTION_DOWN -> { 27 | x1 = event.x 28 | y1 = event.y 29 | } 30 | MotionEvent.ACTION_MOVE -> { 31 | if (vpIsDragging) { 32 | return false 33 | } 34 | x2 = event.x 35 | y2 = event.y 36 | if (abs(x1 - x2) > abs(y1 - y2) && y1 <= 180.dp2px()) { 37 | vpIsDragging = true 38 | return false 39 | } 40 | } 41 | MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { 42 | vpIsDragging = false 43 | } 44 | } 45 | return super.onInterceptTouchEvent(event) 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable-night/selector_bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable-night/splash_windows_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/app_icon.png -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_1.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_2.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_3.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_4.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_avatar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_avatar.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_back.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_back.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_box.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_box.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_collect_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_collect_1.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_collect_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_collect_2.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_exp_light.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_exp_light.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_light.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_light.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/icon_menu.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_common/src/main/res/drawable/icon_menu.webp -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/selector_bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_10dp_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_10dp_grey.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_10dp_grey2.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_10dp_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_10dp_white2.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/shape_login_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /kb_common/src/main/res/drawable/splash_windows_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /kb_common/src/main/res/layout/common_loading_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /kb_common/src/main/res/layout/foot_rv.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | -------------------------------------------------------------------------------- /kb_common/src/main/res/layout/last_rv.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /kb_common/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | N/A 4 | -------------------------------------------------------------------------------- /kb_common/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 20 | 21 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /kb_common/src/test/java/com/stew/kb_common/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_common 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_exp/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_exp/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | 22 | defaultConfig { 23 | externalNativeBuild { 24 | cmake { 25 | cppFlags '' 26 | abiFilters 'arm64-v8a' 27 | //armeabi-v7a 28 | } 29 | } 30 | } 31 | 32 | externalNativeBuild { 33 | cmake { 34 | path file('src/main/cpp/CMakeLists.txt') 35 | version '3.22.1' 36 | } 37 | } 38 | 39 | packagingOptions { 40 | exclude 'lib/arm64-v8a/libhookmalloc.so' 41 | exclude 'lib/arm64-v8a/libtestmalloc.so' 42 | } 43 | } 44 | 45 | dependencies { 46 | implementation project(path: ':kb_common') 47 | } -------------------------------------------------------------------------------- /kb_exp/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_exp/consumer-rules.pro -------------------------------------------------------------------------------- /kb_exp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_exp/src/androidTest/java/com/stew/kb_exp/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_exp.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_exp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_exp/src/main/assets/plugintest.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_exp/src/main/assets/plugintest.apk -------------------------------------------------------------------------------- /kb_exp/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # For more information about using CMake with Android Studio, read the 3 | # documentation: https://d.android.com/studio/projects/add-native-code.html 4 | 5 | # Sets the minimum version of CMake required to build the native library. 6 | 7 | cmake_minimum_required(VERSION 3.22.1) 8 | 9 | project(my_malloc) 10 | 11 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}) 12 | 13 | ADD_SUBDIRECTORY(hookmalloc) 14 | ADD_SUBDIRECTORY(malloc) -------------------------------------------------------------------------------- /kb_exp/src/main/cpp/hookmalloc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Creates and names a library, sets it as either STATIC 4 | # or SHARED, and provides the relative paths to its source code. 5 | # You can define multiple libraries, and CMake builds them for you. 6 | # Gradle automatically packages shared libraries with your APK. 7 | # 8 | #add_library( # Sets the name of the library. 9 | # hookmalloc 10 | # 11 | # # Sets the library as a shared library. 12 | # SHARED 13 | # 14 | # # Provides a relative path to your source file(s). 15 | # HookMalloc.cpp ) 16 | # 17 | ## Searches for a specified prebuilt library and stores the path as a 18 | ## variable. Because CMake includes system libraries in the search path by 19 | ## default, you only need to specify the name of the public NDK library 20 | ## you want to add. CMake verifies that the library exists before 21 | ## completing its build. 22 | # 23 | #find_library( # Sets the name of the path variable. 24 | # log-lib 25 | # 26 | # # Specifies the name of the NDK library that 27 | # # you want CMake to locate. 28 | # log ) 29 | # 30 | ## Specifies libraries CMake should link to your target library. You 31 | ## can link multiple libraries, such as libraries you define in this 32 | ## build script, prebuilt third-party libraries, or system libraries. 33 | # 34 | #target_link_libraries( # Specifies the target library. 35 | # hookmalloc 36 | # 37 | # # Links the target library to the log library 38 | # # included in the NDK. 39 | # ${log-lib} ) 40 | 41 | 42 | 43 | 44 | find_package(bytehook REQUIRED CONFIG) 45 | find_library(log-lib log) 46 | add_library(hookmalloc SHARED HookMalloc.cpp) 47 | target_link_libraries(hookmalloc bytehook::bytehook ${log-lib}) 48 | 49 | 50 | -------------------------------------------------------------------------------- /kb_exp/src/main/cpp/hookmalloc/HookMalloc.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Stew on 2023/10/17. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #define TAG "STEW_Jni_TAG" // 这个是自定义的LOG的标识 9 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) 10 | 11 | #include "bytehook.h" 12 | 13 | 14 | bool ifHook = false; 15 | 16 | 17 | void *malloc_proxy(size_t s) { 18 | //在 CPP 源文件中,也可以改为在代理函数的开头调用 BYTEHOOK_STACK_SCOPE() 宏。 19 | //必须在开头!!! 20 | BYTEHOOK_STACK_SCOPE(); 21 | LOGD("------ size = %d ------",s); 22 | return BYTEHOOK_CALL_PREV(malloc_proxy, s); 23 | } 24 | 25 | 26 | extern "C" 27 | JNIEXPORT void JNICALL 28 | Java_com_stew_kb_1exp_util_TestMallocUtil_StartMalloc(JNIEnv *env, jobject thiz) { 29 | LOGD("------ StartMalloc ------"); 30 | if (ifHook) { 31 | return; 32 | } 33 | ifHook = true; 34 | 35 | bytehook_stub_t s = bytehook_hook_all( 36 | nullptr, 37 | "malloc", 38 | reinterpret_cast(malloc_proxy), 39 | nullptr, nullptr); 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /kb_exp/src/main/cpp/malloc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Creates and names a library, sets it as either STATIC 3 | # or SHARED, and provides the relative paths to its source code. 4 | # You can define multiple libraries, and CMake builds them for you. 5 | # Gradle automatically packages shared libraries with your APK. 6 | 7 | add_library( # Sets the name of the library. 8 | testmalloc 9 | 10 | # Sets the library as a shared library. 11 | SHARED 12 | 13 | # Provides a relative path to your source file(s). 14 | TestMalloc.cpp) 15 | 16 | # Searches for a specified prebuilt library and stores the path as a 17 | # variable. Because CMake includes system libraries in the search path by 18 | # default, you only need to specify the name of the public NDK library 19 | # you want to add. CMake verifies that the library exists before 20 | # completing its build. 21 | 22 | find_library( # Sets the name of the path variable. 23 | log-lib 24 | 25 | # Specifies the name of the NDK library that 26 | # you want CMake to locate. 27 | log ) 28 | 29 | # Specifies libraries CMake should link to your target library. You 30 | # can link multiple libraries, such as libraries you define in this 31 | # build script, prebuilt third-party libraries, or system libraries. 32 | 33 | target_link_libraries( # Specifies the target library. 34 | testmalloc 35 | 36 | # Links the target library to the log library 37 | # included in the NDK. 38 | ${log-lib} ) 39 | -------------------------------------------------------------------------------- /kb_exp/src/main/cpp/malloc/TestMalloc.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Stew on 2023/10/17. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #define TAG "STEW_Jni_TAG" // 这个是自定义的LOG的标识 9 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) 10 | 11 | extern "C" 12 | JNIEXPORT void JNICALL 13 | Java_com_stew_kb_1exp_util_TestMallocUtil_TestMalloc(JNIEnv *env, jobject thiz) { 14 | LOGD("------ TestMalloc ------"); 15 | malloc(88*1024*1024); 16 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/DmActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import android.content.res.Configuration 4 | import android.util.Log 5 | import androidx.appcompat.app.AppCompatDelegate 6 | import com.alibaba.android.arouter.facade.annotation.Route 7 | import com.stew.kb_common.base.BaseActivity 8 | import com.stew.kb_common.util.AppCommonUitl 9 | import com.stew.kb_common.util.Constants 10 | import com.stew.kb_exp.R 11 | import com.stew.kb_exp.databinding.ActivityDmBinding 12 | 13 | /** 14 | * Created by stew on 2024/1/14. 15 | * mail: stewforani@gmail.com 16 | */ 17 | @Route(path = Constants.PATH_DM) 18 | class DmActivity : BaseActivity() { 19 | override fun getLayoutID(): Int { 20 | return R.layout.activity_dm 21 | } 22 | 23 | override fun init() { 24 | mBind.imgBack.setOnClickListener { finish() } 25 | mBind.txLight.setOnClickListener { 26 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 27 | } 28 | mBind.txDark.setOnClickListener { 29 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 30 | } 31 | mBind.txSystem.setOnClickListener { 32 | AppCommonUitl.setFollowSystemTheme() 33 | } 34 | } 35 | 36 | override fun onConfigurationChanged(newConfig: Configuration) { 37 | super.onConfigurationChanged(newConfig) 38 | Log.d(TAG, "onConfigurationChanged: ") 39 | } 40 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/NativeHookActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import com.alibaba.android.arouter.facade.annotation.Route 4 | import com.bytedance.android.bytehook.ByteHook 5 | import com.stew.kb_common.base.BaseActivity 6 | import com.stew.kb_common.util.Constants 7 | import com.stew.kb_exp.R 8 | import com.stew.kb_exp.databinding.ActivityNhBinding 9 | import com.stew.kb_exp.util.TestMallocUtil 10 | 11 | /** 12 | * Created by stew on 2023/10/19. 13 | * mail: stewforani@gmail.com 14 | */ 15 | @Route(path = Constants.PATH_NH) 16 | class NativeHookActivity : BaseActivity() { 17 | 18 | override fun getLayoutID(): Int { 19 | return R.layout.activity_nh 20 | } 21 | 22 | override fun init() { 23 | // 注意:此处so文件也被动态加载so测试所使用(DsActivity) 24 | // 先init,再加载so,因为so文件中的方法需要 btyehook先行初始化 25 | // ByteHook.init() 26 | // System.loadLibrary("hookmalloc") 27 | // System.loadLibrary("testmalloc") 28 | 29 | mBind.imgBack.setOnClickListener { finish() } 30 | 31 | mBind.txStart.setOnClickListener { 32 | TestMallocUtil.startHook() 33 | } 34 | 35 | mBind.txTest.setOnClickListener { 36 | TestMallocUtil.testMalloc() 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/PickImageActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import android.content.Intent 4 | import android.graphics.BitmapFactory 5 | import androidx.activity.result.contract.ActivityResultContracts 6 | import com.alibaba.android.arouter.facade.annotation.Route 7 | import com.stew.kb_common.base.BaseActivity 8 | import com.stew.kb_common.util.Constants 9 | import com.stew.kb_exp.R 10 | import com.stew.kb_exp.databinding.ActivityPickImageBinding 11 | import java.io.InputStream 12 | 13 | /** 14 | * Created by stew on 2024/1/25. 15 | * mail: stewforani@gmail.com 16 | */ 17 | @Route(path = Constants.PATH_PICK_IMAGE) 18 | class PickImageActivity : BaseActivity() { 19 | override fun getLayoutID(): Int { 20 | return R.layout.activity_pick_image 21 | } 22 | 23 | override fun init() { 24 | 25 | val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { 26 | if (it.resultCode == RESULT_OK) { 27 | if (it.data != null && it.data!!.data != null) { 28 | var i: InputStream? =null 29 | try { 30 | i = contentResolver.openInputStream(it.data!!.data!!) as InputStream 31 | mBind.image.setImageBitmap(BitmapFactory.decodeStream(i)) 32 | }catch (e:Exception){ 33 | e.printStackTrace() 34 | }finally { 35 | i?.close() 36 | } 37 | 38 | } 39 | 40 | } 41 | } 42 | 43 | mBind.imgBack.setOnClickListener { finish() } 44 | mBind.txOpen.setOnClickListener { 45 | val i = Intent(Intent.ACTION_OPEN_DOCUMENT) 46 | i.addCategory(Intent.CATEGORY_OPENABLE) 47 | i.type = "image/*" 48 | launcher.launch(i) 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/PluginActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.stew.kb_exp.R 7 | import com.stew.kb_exp.util.PluginLoadUtil 8 | 9 | /** 10 | * Created by stew on 2023/11/20. 11 | * mail: stewforani@gmail.com 12 | */ 13 | public class PluginActivity : AppCompatActivity(){ 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | Log.d(PluginLoadUtil.TAG, "onCreate: ") 17 | setContentView(R.layout.activity_plugin) 18 | } 19 | 20 | override fun onDestroy() { 21 | super.onDestroy() 22 | Log.d(PluginLoadUtil.TAG, "onDestroy: ") 23 | } 24 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/ProxyActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import com.stew.kb_exp.R 6 | 7 | /** 8 | * Created by stew on 2023/11/20. 9 | * mail: stewforani@gmail.com 10 | */ 11 | public class ProxyActivity : Activity(){ 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | setContentView(R.layout.activity_proxy) 15 | } 16 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/RestartAppActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import com.alibaba.android.arouter.facade.annotation.Route 4 | import com.stew.kb_common.base.BaseActivity 5 | import com.stew.kb_common.util.AppCommonUitl 6 | import com.stew.kb_common.util.Constants 7 | import com.stew.kb_exp.R 8 | import com.stew.kb_exp.databinding.ActivityAppBinding 9 | 10 | /** 11 | * Created by stew on 2024/1/16. 12 | * mail: stewforani@gmail.com 13 | */ 14 | @Route(path = Constants.PATH_APP) 15 | class RestartAppActivity : BaseActivity() { 16 | override fun getLayoutID(): Int { 17 | return R.layout.activity_app 18 | } 19 | 20 | override fun init() { 21 | mBind.imgBack.setOnClickListener { finish() } 22 | mBind.tx1.setOnClickListener { 23 | AppCommonUitl.reStartAppByKillProcess() 24 | } 25 | mBind.tx2.setOnClickListener { 26 | AppCommonUitl.reStartAppByClearTop() 27 | } 28 | mBind.tx3.setOnClickListener { 29 | 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/ui/exp/TestPluginApkActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.ui.exp 2 | 3 | import android.content.ComponentName 4 | import android.content.Intent 5 | import android.util.Log 6 | import com.alibaba.android.arouter.facade.annotation.Route 7 | import com.stew.kb_common.base.BaseActivity 8 | import com.stew.kb_common.util.Constants 9 | import com.stew.kb_common.util.ToastUtil 10 | import com.stew.kb_exp.R 11 | import com.stew.kb_exp.databinding.ActivityTpBinding 12 | import com.stew.kb_exp.util.AssetsUtil 13 | import com.stew.kb_exp.util.PluginLoadUtil 14 | import dalvik.system.DexClassLoader 15 | import java.io.File 16 | 17 | /** 18 | * Created by stew on 2024/7/30. 19 | * mail: stewforani@gmail.com 20 | */ 21 | @Route(path = Constants.PATH_TP) 22 | class TestPluginApkActivity : BaseActivity() { 23 | 24 | override fun getLayoutID(): Int { 25 | return R.layout.activity_tp 26 | } 27 | 28 | override fun init() { 29 | 30 | mBind.imgBack.setOnClickListener { finish() } 31 | 32 | mBind.btn1.setOnClickListener { 33 | PluginLoadUtil.init(this, filesDir.absolutePath + File.separator + "app-debug.apk") 34 | } 35 | 36 | mBind.btn3.setOnClickListener { 37 | val c = PluginLoadUtil.pd.loadClass("com.stew.pluginapp.ui.PluginMainActivity") 38 | val intent = Intent(this, c) 39 | startActivity(intent) 40 | 41 | // 非activity的类是可以成功的!!!! 42 | // val c1 = PluginLoadUtil.pd.loadClass("com.stew.pluginapp.utils.PluginString") 43 | // val m = c1.getMethod("getMsg") 44 | // m.isAccessible = true 45 | // ToastUtil.showMsg(m.invoke(c1.newInstance())!!.toString()) 46 | } 47 | 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/util/AssetsUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.util 2 | 3 | import android.content.Context 4 | import java.io.File 5 | import java.io.FileOutputStream 6 | 7 | /** 8 | * Created by stew on 2024/7/29. 9 | * mail: stewforani@gmail.com 10 | */ 11 | object AssetsUtil { 12 | fun copyAssetsToDes(context: Context,name:String,desPath:String){ 13 | try { 14 | val input = context.assets.open(name) 15 | val output = FileOutputStream(File(desPath)) 16 | val buffer = ByteArray(4096) 17 | var byteCount = 0 18 | while (input.read(buffer).also { byteCount = it }!= -1) { 19 | output.write(buffer, 0, byteCount); 20 | } 21 | output.flush() 22 | input.close() 23 | output.close() 24 | }catch (e:Exception){ } 25 | } 26 | } -------------------------------------------------------------------------------- /kb_exp/src/main/java/com/stew/kb_exp/util/TestMallocUtil.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp.util 2 | 3 | /** 4 | * Created by stew on 2023/10/19. 5 | * mail: stewforani@gmail.com 6 | */ 7 | object TestMallocUtil { 8 | 9 | fun startHook() { 10 | StartMalloc() 11 | } 12 | 13 | fun testMalloc() { 14 | TestMalloc() 15 | } 16 | 17 | private external fun TestMalloc(); 18 | private external fun StartMalloc(); 19 | } -------------------------------------------------------------------------------- /kb_exp/src/main/jniLibs/arm64-v8a/libhookmalloc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_exp/src/main/jniLibs/arm64-v8a/libhookmalloc.so -------------------------------------------------------------------------------- /kb_exp/src/main/jniLibs/arm64-v8a/libtestmalloc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_exp/src/main/jniLibs/arm64-v8a/libtestmalloc.so -------------------------------------------------------------------------------- /kb_exp/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_dm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 18 | 19 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | 37 | 38 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_ds.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | 35 | 36 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_nh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | 35 | 36 | 41 | 42 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_pi.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | 36 | 37 | 41 | 42 | 46 | 47 | 51 | 52 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_pick_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 16 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 35 | 36 | 41 | 42 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_proxy.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/layout/activity_tp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | 35 | 36 | 42 | 43 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /kb_exp/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 23 | 24 | -------------------------------------------------------------------------------- /kb_exp/src/test/java/com/stew/kb_exp/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_exp 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_home/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_home/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_home/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_home/consumer-rules.pro -------------------------------------------------------------------------------- /kb_home/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_home/src/androidTest/java/com/stew/kb_home/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_home.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_home/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/adapter/BannerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.adapter 2 | 3 | import android.widget.ImageView 4 | import coil.load 5 | import com.stew.kb_home.R 6 | import com.stew.kb_home.bean.Banner 7 | import com.zhpan.bannerview.BaseBannerAdapter 8 | import com.zhpan.bannerview.BaseViewHolder 9 | 10 | /** 11 | * Created by stew on 8/3/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | class BannerAdapter : BaseBannerAdapter() { 15 | 16 | override fun bindData( 17 | holder: BaseViewHolder?, 18 | data: Banner?, 19 | position: Int, 20 | pageSize: Int 21 | ) { 22 | holder?.findViewById(R.id.image_banner)?.load(data?.imagePath) 23 | } 24 | 25 | override fun getLayoutId(viewType: Int): Int { 26 | return R.layout.item_banner 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/adapter/HomeItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.adapter 2 | 3 | /** 4 | * Created by stew on 8/18/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | interface HomeItemClickListener { 8 | fun onItemClick(position: Int) 9 | fun onCollectClick(position: Int) 10 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/api/HomeApi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.api 2 | 3 | import com.stew.kb_common.network.BaseResp 4 | import com.stew.kb_home.bean.Article 5 | import com.stew.kb_home.bean.Banner 6 | import retrofit2.http.GET 7 | import retrofit2.http.POST 8 | import retrofit2.http.Path 9 | import retrofit2.http.Query 10 | 11 | /** 12 | * Created by stew on 7/30/22. 13 | * mail: stewforani@gmail.com 14 | */ 15 | interface HomeApi { 16 | 17 | //首页banner 18 | @GET("banner/json") 19 | suspend fun getBanner(): BaseResp> 20 | 21 | //首页文章列表 22 | @GET("article/list/{page}/json") 23 | suspend fun getArticleList( 24 | @Path("page") page: Int, 25 | @Query("page_size") page_size: Int 26 | ): BaseResp
27 | 28 | //收藏站内文章 29 | @POST("lg/collect/{id}/json") 30 | suspend fun collect(@Path("id") id: Int): BaseResp 31 | 32 | //取消收藏(文章列表) 33 | @POST("lg/uncollect_originId/{id}/json") 34 | suspend fun unCollect(@Path("id") id: Int): BaseResp 35 | 36 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/bean/Article.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.bean 2 | 3 | /** 4 | * Created by stew on 8/2/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | typealias a = Article.ArticleDetail 8 | 9 | data class Article( 10 | val datas: List, 11 | val over: Boolean, 12 | val curPage: Int 13 | ) { 14 | data class ArticleDetail( 15 | val author: String, 16 | val fresh: Boolean, 17 | val id: Int, 18 | val link: String, 19 | var niceDate: String, 20 | val shareUser: String, 21 | val title: String, 22 | val superChapterId: Int, 23 | val superChapterName: String, 24 | var collect: Boolean 25 | ) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/bean/Banner.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.bean 2 | 3 | /** 4 | * Created by stew on 7/30/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | data class Banner( 8 | val desc: String, 9 | val id: Int, 10 | val imagePath: String, 11 | val isVisible: Int, 12 | val order: Int, 13 | val title: String, 14 | val type: Int, 15 | val url: String 16 | ) 17 | -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/di/HomeModule.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.di 2 | 3 | import com.stew.kb_common.network.RetrofitManager 4 | import com.stew.kb_home.api.HomeApi 5 | import com.stew.kb_home.repo.HomeRepo 6 | import com.stew.kb_home.viewmodel.HomeViewModel 7 | import org.koin.androidx.viewmodel.dsl.viewModel 8 | import org.koin.dsl.module 9 | 10 | /** 11 | * Created by stew on 8/1/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | val homeModule = module { 15 | single { RetrofitManager.getService(HomeApi::class.java) } 16 | single { HomeRepo(get()) } 17 | viewModel { HomeViewModel(get()) } 18 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/repo/HomeRepo.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.repo 2 | 3 | import android.util.Log 4 | import com.stew.kb_common.base.BaseRepository 5 | import com.stew.kb_common.network.BaseResp 6 | import com.stew.kb_common.network.RespStateData 7 | import com.stew.kb_home.api.HomeApi 8 | import com.stew.kb_home.bean.Article 9 | import com.stew.kb_home.bean.Banner 10 | import kotlinx.coroutines.Dispatchers 11 | import kotlinx.coroutines.delay 12 | import kotlinx.coroutines.flow.Flow 13 | import kotlinx.coroutines.flow.flow 14 | import kotlinx.coroutines.flow.flowOn 15 | 16 | /** 17 | * Created by stew on 7/30/22. 18 | * mail: stewforani@gmail.com 19 | */ 20 | class HomeRepo(private val api: HomeApi) : BaseRepository() { 21 | 22 | suspend fun getBanner(data: RespStateData>) { 23 | Log.d("TestSus", "rp1") 24 | dealResp({ api.getBanner() }, data) 25 | Log.d("TestSus", "rp2") 26 | } 27 | 28 | suspend fun getArticle(currentPage: Int, data: RespStateData
) = dealResp( 29 | { api.getArticleList(currentPage, 10) }, data 30 | ) 31 | 32 | suspend fun collect(id: Int, data: RespStateData) = dealResp( 33 | { api.collect(id) }, data 34 | ) 35 | 36 | suspend fun unCollect(id: Int, data: RespStateData) = dealResp( 37 | { api.unCollect(id) }, data 38 | ) 39 | 40 | //flow test 41 | fun getBannerByFlow():Flow>>{ 42 | return flow { 43 | // delay(5000) 44 | val resp = api.getBanner() 45 | emit(resp) 46 | }.flowOn(Dispatchers.IO) 47 | } 48 | 49 | fun getArticleByFlow(currentPage: Int):Flow>{ 50 | return flow { 51 | //delay(5000) 52 | val resp = api.getArticleList(currentPage,10) 53 | emit(resp) 54 | }.flowOn(Dispatchers.IO) 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/ui/HomeTestActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.ui 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.stew.kb_home.R 6 | import org.koin.androidx.viewmodel.ext.android.getViewModel 7 | 8 | /** 9 | * Created by stew on 2024/1/2. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class HomeTestActivity: AppCompatActivity() { 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | setContentView(R.layout.activity_hometest) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_home/src/main/java/com/stew/kb_home/viewmodel/HomeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home.viewmodel 2 | 3 | import android.util.Log 4 | import com.stew.kb_common.base.BaseViewModel 5 | import com.stew.kb_common.network.BaseResp 6 | import com.stew.kb_common.network.RespStateData 7 | import com.stew.kb_home.bean.Article 8 | import com.stew.kb_home.bean.Banner 9 | import com.stew.kb_home.repo.HomeRepo 10 | import kotlinx.coroutines.flow.collectLatest 11 | import kotlinx.coroutines.flow.onCompletion 12 | import kotlinx.coroutines.flow.onStart 13 | import kotlinx.coroutines.flow.zip 14 | 15 | /** 16 | * Created by stew on 7/30/22. 17 | * mail: stewforani@gmail.com 18 | */ 19 | class HomeViewModel(private val repo: HomeRepo) : BaseViewModel() { 20 | 21 | var bannerList = RespStateData>() 22 | var article = RespStateData
() 23 | var collectData = RespStateData() 24 | 25 | fun getBanner() = launch { 26 | Log.d("TestSus", "vm1") 27 | repo.getBanner(bannerList) 28 | Log.d("TestSus", "vm2") 29 | } 30 | 31 | fun getArticle(currentPage: Int) = launch { repo.getArticle(currentPage, article) } 32 | fun collect(id: Int) = launch { repo.collect(id, collectData) } 33 | fun unCollect(id: Int) = launch { repo.unCollect(id, collectData) } 34 | 35 | 36 | //flow test 37 | fun getDataByFlow() = launch { 38 | 39 | val startTime = System.currentTimeMillis() 40 | 41 | // repo.getBannerByFlow().onStart { 42 | // Log.d("HomeViewModel", "getBannerByFlow start") 43 | // }.onCompletion { 44 | // Log.d("HomeViewModel", "getBannerByFlow end") 45 | // }.collectLatest { 46 | // it.responseState = BaseResp.ResponseState.REQUEST_SUCCESS 47 | // bannerList.value = it 48 | // Log.d("HomeViewModel", "getBannerByFlow success") 49 | // } 50 | 51 | repo.getBannerByFlow().zip(repo.getArticleByFlow(0)) { Bbanner, Barticle -> 52 | Bbanner.responseState = BaseResp.ResponseState.REQUEST_SUCCESS 53 | bannerList.value = Bbanner 54 | Barticle.responseState = BaseResp.ResponseState.REQUEST_SUCCESS 55 | article.value = Barticle 56 | }.collect{ 57 | Log.d("FlowTest", "Time: "+(System.currentTimeMillis()-startTime)) 58 | } 59 | 60 | } 61 | } -------------------------------------------------------------------------------- /kb_home/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /kb_home/src/main/res/drawable/shape_tag1.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /kb_home/src/main/res/drawable/shape_tag2.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /kb_home/src/main/res/layout/activity_hometest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /kb_home/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /kb_home/src/main/res/layout/item_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /kb_home/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /kb_home/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 20 | -------------------------------------------------------------------------------- /kb_home/src/test/java/com/stew/kb_home/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_home 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_me/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_me/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_me/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_me/consumer-rules.pro -------------------------------------------------------------------------------- /kb_me/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_me/src/androidTest/java/com/stew/kb_me/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_me.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_me/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/adapter/CollectItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.adapter 2 | 3 | /** 4 | * Created by stew on 8/25/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | fun interface CollectItemClickListener { 8 | fun onClick(position: Int) 9 | } -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/api/MeApi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.api 2 | 3 | import com.stew.kb_common.network.BaseResp 4 | import com.stew.kb_me.bean.MyCollect 5 | import retrofit2.http.GET 6 | import retrofit2.http.Path 7 | import retrofit2.http.Query 8 | 9 | /** 10 | * Created by stew on 8/25/22. 11 | * mail: stewforani@gmail.com 12 | */ 13 | interface MeApi { 14 | //首页文章列表 15 | @GET("lg/collect/list/{page}/json") 16 | suspend fun getCollectList( 17 | @Path("page") page: Int, 18 | @Query("page_size") page_size: Int 19 | ): BaseResp 20 | } -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/bean/MyCollect.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.bean 2 | 3 | /** 4 | * Created by stew on 8/25/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | typealias c = MyCollect.MyCollectDetail 8 | 9 | data class MyCollect( 10 | val datas: List, 11 | val over:Boolean, 12 | val curPage: Int 13 | ) { 14 | data class MyCollectDetail( 15 | val author: String, 16 | val chapterName: String, 17 | val niceDate: String, 18 | val title: String, 19 | val link: String, 20 | val id: Int 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/di/MeModule.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.di 2 | 3 | import com.stew.kb_common.network.RetrofitManager 4 | import com.stew.kb_me.api.MeApi 5 | import com.stew.kb_me.repo.MeRepo 6 | import com.stew.kb_me.viewmodel.MeViewModel 7 | import org.koin.androidx.viewmodel.dsl.viewModel 8 | import org.koin.dsl.module 9 | 10 | /** 11 | * Created by stew on 8/25/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | val meModule = module { 15 | single { RetrofitManager.getService(MeApi::class.java) } 16 | single { MeRepo(get()) } 17 | viewModel { MeViewModel(get()) } 18 | } -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/repo/MeRepo.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.repo 2 | 3 | import com.stew.kb_common.base.BaseRepository 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_me.api.MeApi 6 | import com.stew.kb_me.bean.MyCollect 7 | 8 | /** 9 | * Created by stew on 8/25/22. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class MeRepo(private val api: MeApi) : BaseRepository() { 13 | 14 | suspend fun getCollectList(currentPage: Int, data: RespStateData) = 15 | dealResp({ api.getCollectList(currentPage, 10) }, data) 16 | 17 | } -------------------------------------------------------------------------------- /kb_me/src/main/java/com/stew/kb_me/viewmodel/MeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me.viewmodel 2 | 3 | import com.stew.kb_common.base.BaseViewModel 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_me.bean.MyCollect 6 | import com.stew.kb_me.repo.MeRepo 7 | 8 | /** 9 | * Created by stew on 8/25/22. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class MeViewModel(private val repo: MeRepo) : BaseViewModel() { 13 | 14 | val collectList = RespStateData() 15 | 16 | fun getCollectList(currentPage: Int) = launch { repo.getCollectList(currentPage, collectList) } 17 | } -------------------------------------------------------------------------------- /kb_me/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /kb_me/src/main/res/layout/fragment_collect.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /kb_me/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | -------------------------------------------------------------------------------- /kb_me/src/test/java/com/stew/kb_me/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_me 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_navigation/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_navigation/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_navigation/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_navigation/consumer-rules.pro -------------------------------------------------------------------------------- /kb_navigation/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_navigation/src/androidTest/java/com/stew/kb_navigation/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_navigation.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/adapter/NaviItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.adapter 2 | 3 | /** 4 | * Created by stew on 8/25/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | fun interface NaviItemClickListener { 8 | fun onClick(e: NaviItemEvent) 9 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/adapter/NaviItemEvent.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.adapter 2 | 3 | /** 4 | * Created by stew on 8/25/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | data class NaviItemEvent( 8 | var p1: Int, 9 | var p2: Int, 10 | ) 11 | -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/adapter/NaviVPAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.viewpager2.adapter.FragmentStateAdapter 5 | 6 | class NaviVPAdapter(context: Fragment, private val f: MutableList) : 7 | FragmentStateAdapter(context) { 8 | 9 | override fun getItemCount(): Int { 10 | return f.size 11 | } 12 | 13 | override fun createFragment(position: Int): Fragment { 14 | return f[position] 15 | } 16 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/adapter/SysRVAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import android.widget.TextView 7 | import androidx.recyclerview.widget.AsyncListDiffer 8 | import androidx.recyclerview.widget.DiffUtil 9 | import androidx.recyclerview.widget.RecyclerView 10 | import com.google.android.flexbox.FlexboxLayout 11 | import com.stew.kb_navigation.R 12 | import com.stew.kb_navigation.bean.Sys 13 | 14 | class SysRVAdapter : 15 | RecyclerView.Adapter() { 16 | 17 | private var diff: AsyncListDiffer 18 | 19 | init { 20 | diff = AsyncListDiffer(this, MyCallback()) 21 | } 22 | 23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { 24 | return MyViewHolder( 25 | LayoutInflater.from(parent.context).inflate(R.layout.item_sys_rv, parent, false) 26 | ) 27 | } 28 | 29 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { 30 | val data = diff.currentList[position] 31 | (holder as MyViewHolder).name.text = data.name 32 | holder.flex.removeAllViews() 33 | for (item in data.children){ 34 | val layout = LayoutInflater.from(holder.itemView.context).inflate(R.layout.item_flex, null, false) 35 | val t = layout.findViewById(R.id.tx_flex) 36 | t.text = item.name 37 | holder.flex.addView(layout) 38 | } 39 | } 40 | 41 | override fun getItemCount(): Int { 42 | return diff.currentList.size 43 | } 44 | 45 | fun setData(list: List) { 46 | diff.submitList(list) 47 | } 48 | 49 | class MyViewHolder(item: View) : RecyclerView.ViewHolder(item) { 50 | var name: TextView = item.findViewById(R.id.tx_sys_rv) 51 | var flex:FlexboxLayout = item.findViewById(R.id.flex_sys) 52 | } 53 | 54 | class MyCallback : DiffUtil.ItemCallback() { 55 | override fun areItemsTheSame( 56 | oldItem: Sys, 57 | newItem: Sys 58 | ): Boolean { 59 | return oldItem.id == newItem.id 60 | } 61 | 62 | override fun areContentsTheSame( 63 | oldItem: Sys, 64 | newItem: Sys 65 | ): Boolean { 66 | return oldItem.name == newItem.name 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/api/NaviApi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.api 2 | import com.stew.kb_common.network.BaseResp 3 | import com.stew.kb_navigation.bean.Navi 4 | import com.stew.kb_navigation.bean.Sys 5 | import retrofit2.http.GET 6 | 7 | /** 8 | * Created by stew on 8/7/22. 9 | * mail: stewforani@gmail.com 10 | */ 11 | interface NaviApi { 12 | 13 | //获取导航 14 | @GET("/navi/json") 15 | suspend fun getNavi(): BaseResp> 16 | 17 | //获取体系 18 | @GET("/tree/json") 19 | suspend fun getSys(): BaseResp> 20 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/bean/Navi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.bean 2 | 3 | /** 4 | * Created by stew on 8/8/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | data class Navi( 8 | val cid: Int, 9 | val name: String, 10 | val articles: List 11 | ) { 12 | data class NaviChild( 13 | val id: Int, 14 | val link: String, 15 | val title: String, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/bean/Sys.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.bean 2 | 3 | import java.lang.StringBuilder 4 | 5 | /** 6 | * Created by stew on 8/7/22. 7 | * mail: stewforani@gmail.com 8 | */ 9 | 10 | data class Sys( 11 | val id: Int, 12 | val name: String, 13 | val children: List, 14 | ) { 15 | data class SysChild( 16 | val id: Int, 17 | val name: String, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/di/NaviModule.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.di 2 | 3 | import com.stew.kb_common.network.RetrofitManager 4 | import com.stew.kb_navigation.api.NaviApi 5 | import com.stew.kb_navigation.repo.NaviRepo 6 | import com.stew.kb_navigation.viewmodel.NaviViewModel 7 | import org.koin.androidx.viewmodel.dsl.viewModel 8 | 9 | import org.koin.dsl.module 10 | 11 | /** 12 | * Created by stew on 8/7/22. 13 | * mail: stewforani@gmail.com 14 | */ 15 | val naviModule = module { 16 | single { RetrofitManager.getService(NaviApi::class.java) } 17 | single { NaviRepo(get()) } 18 | viewModel { NaviViewModel(get()) } 19 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/repo/NaviRepo.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.repo 2 | 3 | import com.stew.kb_common.base.BaseRepository 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_navigation.api.NaviApi 6 | import com.stew.kb_navigation.bean.Navi 7 | import com.stew.kb_navigation.bean.Sys 8 | 9 | 10 | /** 11 | * Created by stew on 8/7/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | class NaviRepo(private val api: NaviApi) : BaseRepository() { 15 | suspend fun getSys(data: RespStateData>) = dealResp({ api.getSys() }, data) 16 | suspend fun getNavi(data: RespStateData>) = dealResp({ api.getNavi() }, data) 17 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/ui/MainFragment.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.ui 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.fragment.app.Fragment 6 | import com.google.android.material.tabs.TabLayoutMediator 7 | import com.stew.kb_common.base.BaseFragment 8 | import com.stew.kb_navigation.R 9 | import com.stew.kb_navigation.adapter.NaviVPAdapter 10 | import com.stew.kb_navigation.databinding.FragmentMainBinding 11 | import com.stew.kb_navigation.viewmodel.NaviViewModel 12 | import org.koin.androidx.viewmodel.ext.android.viewModel 13 | 14 | /** 15 | * Created by stew on 8/8/22. 16 | * mail: stewforani@gmail.com 17 | */ 18 | class MainFragment:BaseFragment() { 19 | 20 | val naviViewModel: NaviViewModel by viewModel() 21 | private lateinit var l: MutableList 22 | private lateinit var f: MutableList 23 | 24 | override fun getLayoutID(): Int { 25 | return R.layout.fragment_main 26 | } 27 | 28 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 29 | super.onViewCreated(view, savedInstanceState) 30 | init() 31 | } 32 | 33 | private fun init() { 34 | l = arrayListOf("导航","体系") 35 | f = arrayListOf(NaviFragment(),SysFragment()) 36 | 37 | mBind.viewPager.adapter = NaviVPAdapter(this, f) 38 | TabLayoutMediator(mBind.tabLayout, mBind.viewPager) { tab, position -> 39 | tab.text = l[position] 40 | }.attach() 41 | } 42 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/java/com/stew/kb_navigation/viewmodel/NaviViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation.viewmodel 2 | 3 | 4 | import com.stew.kb_common.base.BaseViewModel 5 | import com.stew.kb_common.network.RespStateData 6 | import com.stew.kb_navigation.bean.Navi 7 | import com.stew.kb_navigation.bean.Sys 8 | import com.stew.kb_navigation.repo.NaviRepo 9 | 10 | /** 11 | * Created by stew on 8/7/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | class NaviViewModel(private val repo: NaviRepo) : BaseViewModel() { 15 | 16 | var naviList = RespStateData>() 17 | var sysList = RespStateData>() 18 | 19 | fun getSys() = launch { repo.getSys(sysList) } 20 | fun getNavi() { launch { repo.getNavi(naviList) }} 21 | } -------------------------------------------------------------------------------- /kb_navigation/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/layout/fragment_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 25 | 26 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/layout/fragment_sys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 19 | 20 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/layout/item_flex.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 20 | 21 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/layout/item_sys.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 19 | 20 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/layout/item_sys_rv.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 22 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /kb_navigation/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /kb_navigation/src/test/java/com/stew/kb_navigation/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_navigation 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_project/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_project/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_project/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_project/consumer-rules.pro -------------------------------------------------------------------------------- /kb_project/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_project/src/androidTest/java/com/stew/kb_project/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_project.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_project/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/adapter/ProItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.adapter 2 | 3 | /** 4 | * Created by stew on 8/18/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | interface ProItemClickListener { 8 | fun onItemClick(position: Int) 9 | fun onCollectClick(position: Int) 10 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/adapter/ProVPAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.viewpager2.adapter.FragmentStateAdapter 5 | 6 | /** 7 | * Created by stew on 8/5/22. 8 | * mail: stewforani@gmail.com 9 | */ 10 | class ProVPAdapter(context: Fragment, private val f: MutableList) : 11 | FragmentStateAdapter(context) { 12 | 13 | override fun getItemCount(): Int { 14 | return f.size 15 | } 16 | 17 | override fun createFragment(position: Int): Fragment { 18 | return f[position] 19 | } 20 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/api/ProjectApi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.api 2 | 3 | import com.stew.kb_common.network.BaseResp 4 | import com.stew.kb_project.bean.Project 5 | import com.stew.kb_project.bean.ProjectType 6 | import retrofit2.http.GET 7 | import retrofit2.http.POST 8 | import retrofit2.http.Path 9 | import retrofit2.http.Query 10 | 11 | /** 12 | * Created by stew on 8/5/22. 13 | * mail: stewforani@gmail.com 14 | */ 15 | interface ProjectApi { 16 | 17 | //获取项目分类 18 | @GET("project/tree/json") 19 | suspend fun getProType(): BaseResp> 20 | 21 | //获取项目列表 22 | @GET("project/list/{page}/json") 23 | suspend fun getProList( 24 | @Path("page") page: Int, 25 | @Query("page_size") page_size: Int, 26 | @Query("cid") cid: Int 27 | ): BaseResp 28 | 29 | //收藏站内文章 30 | @POST("lg/collect/{id}/json") 31 | suspend fun collect(@Path("id") id: Int): BaseResp 32 | 33 | //取消收藏(文章列表) 34 | @POST("lg/uncollect_originId/{id}/json") 35 | suspend fun unCollect(@Path("id") id: Int): BaseResp 36 | 37 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/bean/Project.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.bean 2 | 3 | /** 4 | * Created by stew on 8/5/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | typealias p = Project.ProjectDetail 8 | 9 | data class Project( 10 | val datas: List, 11 | var over: Boolean, 12 | val curPage: Int 13 | ) { 14 | data class ProjectDetail( 15 | val id: Int, 16 | val author: String, 17 | val link: String, 18 | val desc: String, 19 | val niceDate: String, 20 | val envelopePic: String, 21 | val title: String, 22 | var collect: Boolean 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/bean/ProjectType.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.bean 2 | /** 3 | * Created by stew on 8/5/22. 4 | * mail: stewforani@gmail.com 5 | */ 6 | data class ProjectType( 7 | val id: Int, 8 | val name: String, 9 | ) -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/di/ProjectModule.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.di 2 | 3 | import com.stew.kb_common.network.RetrofitManager 4 | import com.stew.kb_project.api.ProjectApi 5 | import com.stew.kb_project.repo.ProjectRepo 6 | import com.stew.kb_project.viewmodel.ProjectViewModel 7 | import org.koin.androidx.viewmodel.dsl.viewModel 8 | import org.koin.dsl.module 9 | 10 | /** 11 | * Created by stew on 8/5/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | val ProjectModule = module { 15 | single { RetrofitManager.getService(ProjectApi::class.java) } 16 | single { ProjectRepo(get()) } 17 | viewModel { ProjectViewModel(get()) } 18 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/repo/ProjectRepo.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.repo 2 | 3 | import com.stew.kb_common.base.BaseRepository 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_project.api.ProjectApi 6 | import com.stew.kb_project.bean.Project 7 | import com.stew.kb_project.bean.ProjectType 8 | 9 | /** 10 | * Created by stew on 8/5/22. 11 | * mail: stewforani@gmail.com 12 | */ 13 | class ProjectRepo(private val api: ProjectApi) : BaseRepository() { 14 | suspend fun getProTypeList(data: RespStateData>) = 15 | dealResp({ api.getProType() }, data) 16 | 17 | suspend fun getProList( 18 | currentPage: Int, 19 | cid: Int, 20 | data: RespStateData 21 | ) = dealResp({ api.getProList(currentPage, 10, cid) }, data) 22 | 23 | suspend fun collect(id: Int, data: RespStateData) = dealResp( 24 | { api.collect(id) }, data 25 | ) 26 | 27 | suspend fun unCollect(id: Int, data: RespStateData) = dealResp( 28 | { api.unCollect(id) }, data 29 | ) 30 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/ui/ProjectFragment.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.google.android.material.tabs.TabLayoutMediator 5 | import com.stew.kb_common.base.BaseVMFragment 6 | import com.stew.kb_common.network.BaseStateObserver 7 | import com.stew.kb_project.R 8 | import com.stew.kb_project.adapter.ProVPAdapter 9 | import com.stew.kb_project.bean.ProjectType 10 | import com.stew.kb_project.databinding.FragmentProjectBinding 11 | import com.stew.kb_project.viewmodel.ProjectViewModel 12 | import org.koin.androidx.viewmodel.ext.android.viewModel 13 | 14 | /** 15 | * Created by stew on 7/27/22. 16 | * mail: stewforani@gmail.com 17 | */ 18 | class ProjectFragment : BaseVMFragment() { 19 | 20 | private val projectViewModel: ProjectViewModel by viewModel() 21 | private var l: MutableList = arrayListOf() 22 | private var f: MutableList = arrayListOf() 23 | 24 | override fun getLayoutID(): Int { 25 | return R.layout.fragment_project 26 | } 27 | 28 | override fun init() { 29 | projectViewModel.getProTypeList() 30 | } 31 | 32 | override fun observe() { 33 | projectViewModel.proTypeList.observe(this, object : BaseStateObserver>(null) { 34 | override fun getRespDataSuccess(it: List) { 35 | initTab(it) 36 | } 37 | }) 38 | } 39 | 40 | private fun initTab(list: List) { 41 | for (i in 0..4) { 42 | l.add((i + 1).toString() + "." + list[i].name) 43 | f.add(ProjectChildFragment.newInstance(list[i].id, i)) 44 | } 45 | mBind.viewPager.adapter = ProVPAdapter(this, f) 46 | mBind.viewPager.offscreenPageLimit = 5 47 | TabLayoutMediator(mBind.tabLayout, mBind.viewPager) { tab, position -> 48 | tab.text = l[position] 49 | }.attach() 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /kb_project/src/main/java/com/stew/kb_project/viewmodel/ProjectViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project.viewmodel 2 | 3 | import com.stew.kb_common.base.BaseViewModel 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_project.bean.Project 6 | import com.stew.kb_project.bean.ProjectType 7 | import com.stew.kb_project.repo.ProjectRepo 8 | 9 | /** 10 | * Created by stew on 8/5/22. 11 | * mail: stewforani@gmail.com 12 | */ 13 | class ProjectViewModel(private var repo: ProjectRepo) : BaseViewModel() { 14 | 15 | var proTypeList = RespStateData>() 16 | var proList = RespStateData() 17 | var collectData = RespStateData() 18 | 19 | fun getProTypeList() = launch( 20 | block = { repo.getProTypeList(proTypeList) } 21 | ) 22 | 23 | fun getProList(currentPage: Int, cid: Int) = launch( 24 | block = { repo.getProList(currentPage, cid, proList) } 25 | ) 26 | 27 | fun collect(id: Int) { 28 | launch( 29 | block = { repo.collect(id, collectData) } 30 | ) 31 | } 32 | 33 | fun unCollect(id: Int) { 34 | launch( 35 | block = { repo.unCollect(id, collectData) } 36 | ) 37 | } 38 | } -------------------------------------------------------------------------------- /kb_project/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /kb_project/src/main/res/layout/fragment_project.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 26 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /kb_project/src/main/res/layout/fragment_project_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /kb_project/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /kb_project/src/test/java/com/stew/kb_project/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_project 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_user/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_user/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_user/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_user/consumer-rules.pro -------------------------------------------------------------------------------- /kb_user/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_user/src/androidTest/java/com/stew/kb_user/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_user.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_user/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/api/UserApi.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.api 2 | 3 | import com.stew.kb_common.network.BaseResp 4 | import com.stew.kb_user.bean.LoginBean 5 | import retrofit2.http.Field 6 | import retrofit2.http.FormUrlEncoded 7 | import retrofit2.http.POST 8 | 9 | /** 10 | * Created by stew on 8/21/22. 11 | * mail: stewforani@gmail.com 12 | */ 13 | interface UserApi { 14 | //登录 15 | @FormUrlEncoded 16 | @POST("user/login") 17 | suspend fun login( 18 | @Field("username") username: String, 19 | @Field("password") password: String 20 | ): BaseResp 21 | } -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/bean/LoginBean.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.bean 2 | 3 | /** 4 | * Created by stew on 8/21/22. 5 | * mail: stewforani@gmail.com 6 | */ 7 | data class LoginBean( 8 | var admin: Boolean, 9 | var chapterTops: List, 10 | var coinCount: Int, 11 | var collectIds: List, 12 | var email: String, 13 | var icon: String, 14 | var id: Int, 15 | var nickname: String, 16 | var password: String, 17 | var publicName: String, 18 | var token: String, 19 | var type: Int, 20 | var username: String 21 | ) 22 | -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/di/UserModule.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.di 2 | 3 | import com.stew.kb_common.network.RetrofitManager 4 | import com.stew.kb_user.api.UserApi 5 | import com.stew.kb_user.repo.LoginRepo 6 | import com.stew.kb_user.viewmodel.LoginViewModel 7 | import org.koin.androidx.viewmodel.dsl.viewModel 8 | import org.koin.dsl.module 9 | 10 | /** 11 | * Created by stew on 8/21/22. 12 | * mail: stewforani@gmail.com 13 | */ 14 | val userModule = module { 15 | single { RetrofitManager.getService(UserApi::class.java) } 16 | single { LoginRepo(get()) } 17 | viewModel { LoginViewModel(get()) } 18 | } -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/repo/LoginRepo.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.repo 2 | 3 | import com.stew.kb_common.base.BaseRepository 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_user.api.UserApi 6 | import com.stew.kb_user.bean.LoginBean 7 | 8 | /** 9 | * Created by stew on 8/21/22. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class LoginRepo(private val api: UserApi) : BaseRepository() { 13 | suspend fun login(username: String, password: String, data: RespStateData) = 14 | dealResp( 15 | block = { api.login(username, password) }, data 16 | ) 17 | 18 | } -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/ui/LoginActivity.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.ui 2 | 3 | import com.alibaba.android.arouter.facade.annotation.Route 4 | import com.stew.kb_common.base.BaseActivity 5 | import com.stew.kb_common.network.BaseStateObserver 6 | import com.stew.kb_common.util.Constants 7 | import com.stew.kb_common.util.KVUtil 8 | import com.stew.kb_common.util.ToastUtil 9 | import com.stew.kb_user.R 10 | import com.stew.kb_user.bean.LoginBean 11 | import com.stew.kb_user.databinding.ActivityLoginBinding 12 | import com.stew.kb_user.viewmodel.LoginViewModel 13 | import org.koin.androidx.viewmodel.ext.android.viewModel 14 | 15 | 16 | /** 17 | * Created by stew on 8/21/22. 18 | * mail: stewforani@gmail.com 19 | */ 20 | @Route(path = Constants.PATH_LOGIN) 21 | class LoginActivity : BaseActivity() { 22 | 23 | private val loginViewModel: LoginViewModel by viewModel() 24 | 25 | override fun getLayoutID(): Int { 26 | return R.layout.activity_login 27 | } 28 | 29 | override fun init() { 30 | loginViewModel.loginData.observe(this, object : BaseStateObserver(null) { 31 | override fun getRespDataSuccess(it: LoginBean) { 32 | KVUtil.put(Constants.USER_NAME, it.username) 33 | ToastUtil.showMsg("登陆成功!") 34 | finish() 35 | } 36 | }) 37 | 38 | mBind.txLogin.setOnClickListener { 39 | if (mBind.edit1.text.isNotEmpty() && mBind.edit2.text.isNotEmpty()) { 40 | loginViewModel.login(mBind.edit1.text.toString(), mBind.edit2.text.toString()) 41 | } else { 42 | ToastUtil.showMsg("输入有误!") 43 | } 44 | } 45 | 46 | mBind.imgBack.setOnClickListener { finish() } 47 | 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /kb_user/src/main/java/com/stew/kb_user/viewmodel/LoginViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user.viewmodel 2 | 3 | import com.stew.kb_common.base.BaseViewModel 4 | import com.stew.kb_common.network.RespStateData 5 | import com.stew.kb_user.bean.LoginBean 6 | import com.stew.kb_user.repo.LoginRepo 7 | 8 | /** 9 | * Created by stew on 8/21/22. 10 | * mail: stewforani@gmail.com 11 | */ 12 | class LoginViewModel(private val repo: LoginRepo) : BaseViewModel() { 13 | 14 | var loginData = RespStateData() 15 | 16 | fun login(username: String, password: String) { 17 | launch( 18 | block = { 19 | repo.login(username, password,loginData) 20 | } 21 | ) 22 | } 23 | } -------------------------------------------------------------------------------- /kb_user/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /kb_user/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /kb_user/src/test/java/com/stew/kb_user/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_user 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /kb_web/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kb_web/build.gradle: -------------------------------------------------------------------------------- 1 | if (singleModule.toBoolean()) { 2 | apply plugin: 'com.android.application' 3 | } else { 4 | apply plugin: 'com.android.library' 5 | } 6 | 7 | apply from: '../dependencies.gradle' 8 | 9 | android { 10 | sourceSets { 11 | main { 12 | if (singleModule.toBoolean()) { 13 | //如果是application,则编译主目录下AndroidManifest.xml 14 | manifest.srcFile 'src/main/AndroidManifest.xml' 15 | } else { 16 | //如果是library,则编译manifest下AndroidManifest.xml 17 | manifest.srcFile 'src/main/manifest/AndroidManifest.xml' 18 | } 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project(path: ':kb_common') 25 | } -------------------------------------------------------------------------------- /kb_web/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stewForAni/KotlinBox-WanAndroid/a3e90f70edcf44b6032882607530551b1b92cdd7/kb_web/consumer-rules.pro -------------------------------------------------------------------------------- /kb_web/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /kb_web/src/androidTest/java/com/stew/kb_web/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_web 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.stew.kb_web.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /kb_web/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kb_web/src/main/manifest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /kb_web/src/main/res/layout/activity_web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 16 | 17 | 21 | 22 | 27 | 28 | 29 | 30 | 33 | 34 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /kb_web/src/test/java/com/stew/kb_web/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.stew.kb_web 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':kb_user' 2 | include ':kb_me' 3 | include ':kb_navigation' 4 | include ':kb_project' 5 | include ':kb_home' 6 | include ':kb_common' 7 | include ':app' 8 | rootProject.name = "KotlinBox" 9 | include ':kb_web' 10 | include ':app_plugin' 11 | include ':kb_exp' 12 | --------------------------------------------------------------------------------