├── .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 |
4 |
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 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------