├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── themes.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── values-night │ │ │ └── themes.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout │ │ │ └── activity_main.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── assets │ │ └── monitor.properties │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── android │ │ └── monitor │ │ └── demo │ │ └── MainActivity.kt ├── proguard-rules.pro └── build.gradle ├── monitor ├── .gitignore ├── consumer-rules.pro ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── dimens.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── mipmap-xxhdpi │ │ │ ├── monitor_logo.png │ │ │ ├── monitor_icon_menu.png │ │ │ ├── monitor_app_back_icon.png │ │ │ ├── monitor_icon_tab_file.png │ │ │ ├── monitor_icon_right_arrow.png │ │ │ ├── monitor_icon_share_white.png │ │ │ └── monitor_icon_tab_network.png │ │ ├── drawable │ │ │ ├── bg_flutter_tag.xml │ │ │ ├── bg_monitor_theme.xml │ │ │ ├── bg_radio_center.xml │ │ │ ├── bg_radio_left.xml │ │ │ └── bg_radio_right.xml │ │ ├── anim │ │ │ ├── bottom_to_top.xml │ │ │ └── top_to_bottom.xml │ │ ├── color │ │ │ └── text_color_radio.xml │ │ ├── menu │ │ │ └── bottom_nav_menu.xml │ │ └── layout │ │ │ ├── include_status_bar_view_layout.xml │ │ │ ├── fragment_monitor_main.xml │ │ │ ├── fragment_sp_list.xml │ │ │ ├── item_sp_file.xml │ │ │ ├── item_sp_file_detail.xml │ │ │ ├── activity_monitor_detail.xml │ │ │ ├── dialog_sp_modify.xml │ │ │ ├── activity_monitor_main.xml │ │ │ ├── activity_sp_file_detail.xml │ │ │ ├── item_monitor.xml │ │ │ ├── fragment_monitor_request.xml │ │ │ ├── fragment_monitor_response.xml │ │ │ └── activity_monitor_config.xml │ │ ├── java │ │ └── com │ │ │ └── lygttpod │ │ │ └── monitor │ │ │ ├── data │ │ │ ├── HttpHeader.kt │ │ │ ├── SpValueInfo.kt │ │ │ ├── PropertiesData.kt │ │ │ ├── SpData.kt │ │ │ └── MonitorData.kt │ │ │ ├── enum │ │ │ ├── WeakNetworkType.kt │ │ │ └── SPValueType.kt │ │ │ ├── utils │ │ │ ├── GlobalConfig.kt │ │ │ ├── DateKtx.kt │ │ │ ├── ServiceDataProvider.kt │ │ │ ├── NetworkHelper.kt │ │ │ ├── FormatHelper.kt │ │ │ ├── GsonHelper.kt │ │ │ ├── StringKtx.kt │ │ │ ├── MonitorProperties.kt │ │ │ ├── OkHttpKtx.kt │ │ │ └── SPUtils.kt │ │ │ ├── room │ │ │ ├── MonitorDatabase.kt │ │ │ └── MonitorDao.kt │ │ │ ├── interceptor │ │ │ ├── MonitorMockInterceptor.kt │ │ │ ├── MonitorMockResponseInterceptor.kt │ │ │ ├── MonitorWeakNetworkInterceptor.kt │ │ │ └── MonitorInterceptor.kt │ │ │ ├── adapter │ │ │ ├── MonitorPagerAdapter.kt │ │ │ └── MonitorListAdapter.kt │ │ │ ├── provider │ │ │ └── MonitorProvider.kt │ │ │ ├── ui │ │ │ ├── sp │ │ │ │ ├── SpFileAdapter.kt │ │ │ │ ├── SpFileDetailAdapter.kt │ │ │ │ ├── SPFileListFragment.kt │ │ │ │ └── SPFileDetailActivity.kt │ │ │ ├── MonitorRequestFragment.kt │ │ │ ├── MonitorResponseFragment.kt │ │ │ ├── request │ │ │ │ └── MonitorMainFragment.kt │ │ │ ├── MonitorDetailActivity.kt │ │ │ ├── MonitorMainActivity.kt │ │ │ ├── dialog │ │ │ │ └── SpModifyDialog.kt │ │ │ └── MonitorConfigActivity.kt │ │ │ ├── mock │ │ │ └── MockHelper.kt │ │ │ ├── weaknetwork │ │ │ ├── SpeedLimitResponseBody.kt │ │ │ └── WeakNetworkHelper.kt │ │ │ ├── service │ │ │ └── MonitorService.kt │ │ │ └── MonitorHelper.kt │ │ ├── AndroidManifest.xml │ │ └── assets │ │ └── sp_index.html ├── gradle.properties ├── proguard-rules.pro └── build.gradle ├── monitor-plugin ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── gradle-plugins │ │ │ └── monitor-plugin.properties │ │ └── kotlin │ │ └── com │ │ └── lygttpod │ │ └── monitor │ │ ├── okhttp │ │ ├── OkHttpWeaver.kt │ │ ├── OkHttpTransform.kt │ │ ├── OkHttpMethodAdapter.kt │ │ └── OkHttpClassVisitor.kt │ │ └── plugin │ │ └── MonitorPlugin.kt ├── gradle.properties └── build.gradle ├── android-secring.gpg ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── settings.gradle ├── .gitignore ├── upload.gradle ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /monitor/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /monitor-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /monitor/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | # monitor 2 | -keep class com.lygttpod.monitor.** { *; } -------------------------------------------------------------------------------- /android-secring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/android-secring.gpg -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /monitor/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 抓包 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "AndroidMonitor" 2 | include ':app' 3 | include ':monitor' 4 | include ':monitor-plugin' 5 | -------------------------------------------------------------------------------- /monitor/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=monitor 2 | VERSION_NAME=0.1.2 3 | POM_NAME=monitor 4 | # 是否发布到本地 5 | UPLOAD_LOCAL=false -------------------------------------------------------------------------------- /monitor-plugin/src/main/resources/META-INF/gradle-plugins/monitor-plugin.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.lygttpod.monitor.plugin.MonitorPlugin -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /monitor-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=monitor-plugin 2 | VERSION_NAME=0.0.2 3 | POM_NAME=monitor-plugin 4 | # 是否发布到本地 5 | UPLOAD_LOCAL=false -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/data/HttpHeader.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.data 2 | 3 | data class HttpHeader(val name: String, val value: String) -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_icon_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_icon_menu.png -------------------------------------------------------------------------------- /monitor/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 30dp 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | /local.properties 5 | /.idea/ 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .cxx 11 | local.properties 12 | -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_app_back_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_app_back_icon.png -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_icon_tab_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_icon_tab_file.png -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_icon_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_icon_right_arrow.png -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_icon_share_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_icon_share_white.png -------------------------------------------------------------------------------- /monitor/src/main/res/mipmap-xxhdpi/monitor_icon_tab_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lygttpod/AndroidMonitor/HEAD/monitor/src/main/res/mipmap-xxhdpi/monitor_icon_tab_network.png -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/data/SpValueInfo.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.data 2 | 3 | import com.lygttpod.monitor.enum.SPValueType 4 | 5 | class SpValueInfo(val value: Any?, val type: SPValueType = SPValueType.String) -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/enum/WeakNetworkType.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.enum 2 | 3 | enum class WeakNetworkType { 4 | //超时 5 | TIME_OUT, 6 | 7 | //限速 8 | SPEED_LIMIT, 9 | 10 | //断网 11 | NO_NETWORK 12 | } -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidMonitor 3 | AndroidMonitor抓包 4 | 1、局域网内通过电脑浏览器打开上述服务地址\n2、点击发送请求\n3、在网页端或手机抓包app可以查看请求数据 5 | -------------------------------------------------------------------------------- /monitor/src/main/res/drawable/bg_flutter_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /monitor/src/main/res/anim/bottom_to_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /monitor/src/main/res/anim/top_to_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jul 06 20:00:06 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/enum/SPValueType.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.enum 2 | 3 | enum class SPValueType(val value: kotlin.String) { 4 | Int("Int"), 5 | Double("Double"), 6 | Long("Long"), 7 | Float("Float"), 8 | String("String"), 9 | Boolean("Boolean"); 10 | } -------------------------------------------------------------------------------- /monitor/src/main/res/color/text_color_radio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/utils/GlobalConfig.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.utils 2 | 3 | 4 | var lastUpdateDataId = 0L 5 | 6 | /** 7 | * content-type类型 https://www.runoob.com/http/http-content-type.html 8 | */ 9 | var defaultContentTypes = "application/json,application/xml,text/html,text/plain,text/xml" 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /monitor/src/main/res/drawable/bg_monitor_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/data/PropertiesData.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.data 2 | 3 | class PropertiesData( 4 | var port: String, 5 | var dbName: String, 6 | var whiteContentTypes: String?,//ContentType白名单 7 | var whiteHosts: String?,//host白名单 8 | var blackHosts: String?,//host黑名单 9 | var isFilterIPAddressHost: Boolean = false//是否过滤纯IP地址的host 10 | ) -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/data/SpData.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.data 2 | 3 | /** 4 | *
 5 |  *      author  : Allen
 6 |  *      date    : 2022/8/6
 7 |  *      desc    :
 8 |  * 
9 | */ 10 | data class SpData( 11 | val fileName: String?, 12 | val subList: List? = null 13 | ) 14 | 15 | data class SpSubData(val keyName: String?, var keyValue: SpValueInfo?) 16 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/room/MonitorDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.room 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.lygttpod.monitor.data.MonitorData 6 | 7 | @Database(entities = [MonitorData::class], version = 1, exportSchema = false) 8 | abstract class MonitorDatabase : RoomDatabase() { 9 | 10 | abstract fun monitorDao(): MonitorDao 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /monitor-plugin/src/main/kotlin/com/lygttpod/monitor/okhttp/OkHttpWeaver.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.okhttp 2 | 3 | import com.quinn.hunter.transform.asm.BaseWeaver 4 | import org.objectweb.asm.ClassVisitor 5 | import org.objectweb.asm.ClassWriter 6 | 7 | 8 | class OkHttpWeaver : BaseWeaver() { 9 | 10 | override fun wrapClassWriter(classWriter: ClassWriter?): ClassVisitor { 11 | return OkHttpClassVisitor(classWriter) 12 | } 13 | } -------------------------------------------------------------------------------- /monitor-plugin/src/main/kotlin/com/lygttpod/monitor/okhttp/OkHttpTransform.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.okhttp 2 | 3 | import com.quinn.hunter.transform.HunterTransform 4 | import com.quinn.hunter.transform.RunVariant 5 | import org.gradle.api.Project 6 | 7 | class OkHttpTransform(project: Project?) : HunterTransform(project) { 8 | init { this.bytecodeWeaver = OkHttpWeaver() } 9 | 10 | override fun getRunVariant(): RunVariant { 11 | return RunVariant.DEBUG 12 | } 13 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/utils/DateKtx.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.utils 2 | 3 | import java.text.SimpleDateFormat 4 | import java.util.* 5 | 6 | val TIME_SHORT = SimpleDateFormat("HH:mm:ss SSS", Locale.CHINA) 7 | 8 | val TIME_LONG = SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS", Locale.CHINA) 9 | 10 | fun Date?.formatData(format: SimpleDateFormat = TIME_SHORT): String { 11 | return if (this == null) { 12 | "" 13 | } else format.format(this) 14 | } 15 | -------------------------------------------------------------------------------- /monitor/src/main/res/menu/bottom_nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /monitor/src/main/res/layout/include_status_bar_view_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/utils/ServiceDataProvider.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.utils 2 | 3 | import com.lygttpod.monitor.MonitorHelper 4 | import com.lygttpod.monitor.data.MonitorData 5 | 6 | object ServiceDataProvider { 7 | 8 | fun getMonitorDataList(limit: Int = 50, offset: Int = 0): MutableList { 9 | return MonitorHelper.getMonitorDataList(limit, offset) 10 | } 11 | 12 | fun getMonitorDataByLastId(lastUpdateDataId: Long): MutableList { 13 | return MonitorHelper.getMonitorDataByLastId(lastUpdateDataId) 14 | } 15 | } -------------------------------------------------------------------------------- /monitor-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | apply plugin: 'kotlin' 3 | 4 | //gradle 开发 sdk 依赖 5 | dependencies { 6 | implementation gradleApi() 7 | implementation localGroovy() 8 | 9 | //noinspection GradleDependency 10 | implementation 'org.ow2.asm:asm:7.1' 11 | //noinspection GradleDependency 12 | implementation 'org.ow2.asm:asm-util:7.1' 13 | //noinspection GradleDependency 14 | implementation 'org.ow2.asm:asm-commons:7.1' 15 | implementation 'com.android.tools.build:gradle:4.1.3' 16 | implementation 'cn.quinnchen.hunter:hunter-transform:1.2.3' 17 | } 18 | 19 | apply from: '../upload.gradle' -------------------------------------------------------------------------------- /monitor/src/main/res/drawable/bg_radio_center.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/assets/monitor.properties: -------------------------------------------------------------------------------- 1 | # 抓包助手参数配置 2 | # Default port = 9527 3 | # Default dbName = monitor_room_db 4 | # ContentTypes白名单,默认application/json,application/xml,text/html,text/plain,text/xml 5 | # Default whiteContentTypes = application/json,application/xml,text/html,text/plain,text/xml 6 | # Hosts白名单,默认全部是白名单 7 | # Default whiteHosts = 8 | # Hosts黑名单,默认没有黑名单 9 | # Default blackHosts = 10 | # 是否过滤纯IP地址的host 默认false 11 | # Default isFilterIPAddressHost = false 12 | 13 | # 如何多个项目都集成抓包工具,可以设置不同的端口进行访问,端口号唯一 14 | monitor.port=9527 15 | monitor.dbName=demo_monitor_room_db 16 | monitor.whiteContentTypes=application/json,application/xml,text/html,text/plain,text/xml 17 | monitor.isFilterIPAddressHost=false -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/interceptor/MonitorMockInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.interceptor 2 | 3 | import android.net.Uri 4 | import com.lygttpod.monitor.mock.MockHelper 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | 8 | class MonitorMockInterceptor : Interceptor { 9 | override fun intercept(chain: Interceptor.Chain): Response { 10 | val request = chain.request() 11 | val url = request.url.toString() 12 | val path = Uri.parse(url).path 13 | if (MockHelper.isMockByNetworkResponse(path)) { 14 | return MockHelper.buildMockServer(chain, request) 15 | } 16 | return chain.proceed(request) 17 | } 18 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/interceptor/MonitorMockResponseInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.interceptor 2 | 3 | import android.net.Uri 4 | import com.lygttpod.monitor.mock.MockHelper 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | 8 | class MonitorMockResponseInterceptor : Interceptor { 9 | override fun intercept(chain: Interceptor.Chain): Response { 10 | val request = chain.request() 11 | val url = request.url.toString() 12 | val path = Uri.parse(url).path 13 | if (MockHelper.isMockByCustomResponse(path)) { 14 | return MockHelper.mockResponseBody(chain) 15 | } 16 | return chain.proceed(request) 17 | } 18 | } -------------------------------------------------------------------------------- /monitor/src/main/res/drawable/bg_radio_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /monitor/src/main/res/drawable/bg_radio_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/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 -------------------------------------------------------------------------------- /monitor/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 -------------------------------------------------------------------------------- /monitor/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #5dbdf7 4 | #5d91f7 5 | #D81B60 6 | #e6e6e6 7 | 8 | #2E3032 9 | #888F86 10 | #F44336 11 | #2196F3 12 | #673AB7 13 | #26E79F 14 | 15 | #ffffff 16 | #000000 17 | #22aaaaaa 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/interceptor/MonitorWeakNetworkInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.interceptor 2 | 3 | import com.lygttpod.monitor.enum.WeakNetworkType 4 | import com.lygttpod.monitor.weaknetwork.WeakNetworkHelper 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | 8 | class MonitorWeakNetworkInterceptor : Interceptor { 9 | 10 | override fun intercept(chain: Interceptor.Chain): Response { 11 | if (!WeakNetworkHelper.isOpen) { 12 | return chain.proceed(chain.request()) 13 | } 14 | return when (WeakNetworkHelper.weakNetType()) { 15 | WeakNetworkType.TIME_OUT -> { 16 | WeakNetworkHelper.mockTimeout(chain) 17 | } 18 | WeakNetworkType.SPEED_LIMIT -> { 19 | WeakNetworkHelper.mockSpeedLimit(chain) 20 | } 21 | WeakNetworkType.NO_NETWORK -> { 22 | WeakNetworkHelper.mockNoNetwork(chain) 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/adapter/MonitorPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentManager 5 | import androidx.fragment.app.FragmentPagerAdapter 6 | 7 | 8 | class MonitorPagerAdapter constructor(fm: FragmentManager) : 9 | FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { 10 | 11 | private val fragmentList = ArrayList() 12 | 13 | private val fragmentTitleList = ArrayList() 14 | 15 | internal fun addFragment(fragment: Fragment, title: String) { 16 | fragmentList.add(fragment) 17 | fragmentTitleList.add(title) 18 | } 19 | 20 | override fun getItem(position: Int): Fragment { 21 | return fragmentList[position] 22 | } 23 | 24 | override fun getCount(): Int { 25 | return fragmentList.size 26 | } 27 | 28 | override fun getPageTitle(position: Int): CharSequence { 29 | return fragmentTitleList[position] 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/utils/NetworkHelper.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.utils 2 | 3 | import android.util.Log 4 | import java.net.Inet4Address 5 | import java.net.NetworkInterface 6 | import java.net.SocketException 7 | 8 | fun getPhoneWifiIpAddress(): String? { 9 | try { 10 | val networkInterfaces = NetworkInterface.getNetworkInterfaces() ?: return null 11 | while (networkInterfaces.hasMoreElements()) { 12 | val networkInterface = networkInterfaces.nextElement() 13 | val inetAddresses = networkInterface.inetAddresses 14 | while (inetAddresses.hasMoreElements()) { 15 | val inetAddress = inetAddresses.nextElement() 16 | if (!inetAddress.isLoopbackAddress && inetAddress is Inet4Address) { 17 | return inetAddress.getHostAddress() 18 | } 19 | } 20 | } 21 | } catch (e: SocketException) { 22 | Log.e("MonitorPCService", "get ip", e) 23 | return null 24 | } 25 | return null 26 | } -------------------------------------------------------------------------------- /monitor/src/main/res/layout/fragment_monitor_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /monitor-plugin/src/main/kotlin/com/lygttpod/monitor/okhttp/OkHttpMethodAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.okhttp 2 | 3 | import org.objectweb.asm.MethodVisitor 4 | import org.objectweb.asm.Opcodes 5 | import org.objectweb.asm.commons.AdviceAdapter 6 | 7 | class OkHttpMethodAdapter(methodVisitor: MethodVisitor?, access: Int, name: String?, descriptor: String?) : AdviceAdapter(Opcodes.ASM7, methodVisitor, access, name, descriptor) { 8 | 9 | override fun onMethodExit(opcode: Int) { 10 | super.onMethodExit(opcode) 11 | mv?.let { 12 | it.visitVarInsn(ALOAD, 0) 13 | it.visitFieldInsn(GETFIELD, "okhttp3/OkHttpClient\$Builder", "interceptors", "Ljava/util/List;") 14 | it.visitFieldInsn(GETSTATIC, "com/lygttpod/monitor/MonitorHelper", "INSTANCE", "Lcom/lygttpod/monitor/MonitorHelper;") 15 | it.visitMethodInsn(INVOKEVIRTUAL, "com/lygttpod/monitor/MonitorHelper", "getHookInterceptors", "()Ljava/util/List;", false) 16 | it.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "addAll", "(Ljava/util/Collection;)Z", true) 17 | it.visitInsn(POP) 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /upload.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.vanniktech.maven.publish' 2 | 3 | allprojects { 4 | plugins.withId("com.vanniktech.maven.publish") { 5 | mavenPublish { 6 | sonatypeHost = "S01" 7 | } 8 | } 9 | } 10 | 11 | publishing { 12 | repositories { 13 | maven { 14 | allowInsecureProtocol = true 15 | def uploadLocal = findProperty("UPLOAD_LOCAL") ? UPLOAD_LOCAL : "false" 16 | if (new Boolean(uploadLocal)) { 17 | String homeDir = System.getProperty("user.home") 18 | url = "file://$homeDir/maven/repos/" 19 | } else { 20 | url = version.endsWith('SNAPSHOT') ? mavenSnapshotsUrl : mavenReleasesUrl 21 | credentials { 22 | def localProperties = new Properties() 23 | localProperties.load(new FileInputStream(rootProject.file("local.properties"))) 24 | username = localProperties.getProperty('mavenCentralUsername') 25 | password = localProperties.getProperty('mavenCentralPassword') 26 | } 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /monitor-plugin/src/main/kotlin/com/lygttpod/monitor/plugin/MonitorPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.plugin 2 | 3 | import com.android.build.gradle.AppExtension 4 | import com.lygttpod.monitor.okhttp.OkHttpTransform 5 | import org.gradle.api.Plugin 6 | import org.gradle.api.Project 7 | import java.util.* 8 | 9 | class MonitorPlugin : Plugin { 10 | 11 | override fun apply(project: Project) { 12 | var enableMonitorPlugin = true 13 | val properties = Properties() 14 | val file = project.rootProject.file("local.properties") 15 | if (file.exists()) { 16 | properties.load(file.inputStream()) 17 | enableMonitorPlugin = properties.getProperty("monitor.enablePlugin", "true")?.toBoolean() ?: true 18 | } 19 | println("MonitorPlugin---->enableMonitorPlugin = $enableMonitorPlugin") 20 | if (!enableMonitorPlugin) return 21 | try { 22 | val appException: AppExtension = project.extensions.getByName("android") as AppExtension 23 | appException.registerTransform(OkHttpTransform(project)) 24 | } catch (e: Exception) { 25 | e.printStackTrace() 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /monitor/src/main/res/layout/fragment_sp_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/room/MonitorDao.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.room 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import com.lygttpod.monitor.data.MonitorData 6 | 7 | @Dao 8 | interface MonitorDao { 9 | @Query("SELECT * FROM monitor WHERE id > :lastId ORDER BY id DESC") 10 | fun queryByLastIdForAndroid(lastId: Long): LiveData> 11 | 12 | @Query("SELECT * FROM monitor ORDER BY id DESC LIMIT :limit OFFSET :offset") 13 | fun queryByOffsetForAndroid(limit: Int, offset: Int): LiveData> 14 | 15 | @Query("SELECT * FROM monitor") 16 | fun queryAllForAndroid(): LiveData> 17 | 18 | @Query("SELECT * FROM monitor WHERE id > :lastId ORDER BY id DESC") 19 | fun queryByLastId(lastId: Long): MutableList 20 | 21 | @Query("SELECT * FROM monitor ORDER BY id DESC LIMIT :limit OFFSET :offset") 22 | fun queryByOffset(limit: Int, offset: Int): MutableList 23 | 24 | @Query("SELECT * FROM monitor") 25 | fun queryAll(): MutableList 26 | 27 | @Insert 28 | fun insert(data: MonitorData) 29 | 30 | @Update 31 | fun update(data: MonitorData) 32 | 33 | @Query("DELETE FROM monitor") 34 | fun deleteAll() 35 | } -------------------------------------------------------------------------------- /monitor-plugin/src/main/kotlin/com/lygttpod/monitor/okhttp/OkHttpClassVisitor.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.okhttp 2 | 3 | import org.objectweb.asm.ClassVisitor 4 | import org.objectweb.asm.MethodVisitor 5 | import org.objectweb.asm.Opcodes 6 | 7 | class OkHttpClassVisitor : ClassVisitor { 8 | 9 | private var className: String? = null 10 | 11 | constructor(api: Int, classVisitor: ClassVisitor?) : super(api, classVisitor) 12 | constructor(classVisitor: ClassVisitor?) : this(Opcodes.ASM7, classVisitor) 13 | 14 | override fun visit(version: Int, access: Int, name: String?, signature: String?, superName: String?, interfaces: Array?) { 15 | super.visit(version, access, name, signature, superName, interfaces) 16 | this.className = name 17 | } 18 | 19 | override fun visitMethod(access: Int, name: String?, descriptor: String?, signature: String?, exceptions: Array?): MethodVisitor? { 20 | val methodVisitor = cv.visitMethod(access, name, descriptor, signature, exceptions) 21 | return if (className == "okhttp3/OkHttpClient\$Builder" && name == "") { 22 | if (methodVisitor == null) null else OkHttpMethodAdapter(methodVisitor, access, name, descriptor) 23 | } else { 24 | methodVisitor 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/provider/MonitorProvider.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.provider 2 | 3 | import android.content.ContentProvider 4 | import android.content.ContentValues 5 | import android.database.Cursor 6 | import android.net.Uri 7 | import android.util.Log 8 | import com.lygttpod.monitor.MonitorHelper 9 | 10 | class MonitorProvider : ContentProvider() { 11 | override fun onCreate(): Boolean { 12 | val context = context 13 | if (context == null) { 14 | Log.e("MonitorProvider", "MonitorProvider初始化context失败") 15 | } else { 16 | MonitorHelper.init(context) 17 | } 18 | return true 19 | } 20 | 21 | override fun insert(uri: Uri, values: ContentValues?): Uri? = null 22 | 23 | override fun query( 24 | uri: Uri, 25 | projection: Array?, 26 | selection: String?, 27 | selectionArgs: Array?, 28 | sortOrder: String? 29 | ): Cursor? = null 30 | 31 | override fun update( 32 | uri: Uri, 33 | values: ContentValues?, 34 | selection: String?, 35 | selectionArgs: Array? 36 | ): Int = 0 37 | 38 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = 0 39 | 40 | override fun getType(uri: Uri): String? = null 41 | } -------------------------------------------------------------------------------- /monitor/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 21 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | //2、应用抓包插件 5 | id 'monitor-plugin' 6 | } 7 | 8 | android { 9 | compileSdk 31 10 | 11 | defaultConfig { 12 | applicationId "com.android.monitor.demo" 13 | minSdk 21 14 | targetSdk 31 15 | versionCode 1 16 | versionName "1.0" 17 | 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | kotlinOptions { 32 | jvmTarget = '1.8' 33 | } 34 | buildFeatures { 35 | viewBinding true 36 | } 37 | } 38 | 39 | dependencies { 40 | 41 | implementation 'androidx.core:core-ktx:1.7.0' 42 | implementation 'androidx.appcompat:appcompat:1.3.0' 43 | implementation 'com.google.android.material:material:1.4.0' 44 | implementation 'com.squareup.okhttp3:okhttp:4.9.3' 45 | 46 | //3、依赖抓包库 只在debug环境下依赖 所有使用 debugImplementation 47 | // debugImplementation 'io.github.lygttpod:monitor:0.0.8' 48 | debugImplementation project(":monitor") 49 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/utils/FormatHelper.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.utils 2 | 3 | import org.xml.sax.InputSource 4 | import java.io.ByteArrayInputStream 5 | import java.io.ByteArrayOutputStream 6 | import javax.xml.transform.OutputKeys 7 | import javax.xml.transform.sax.SAXSource 8 | import javax.xml.transform.sax.SAXTransformerFactory 9 | import javax.xml.transform.stream.StreamResult 10 | 11 | 12 | fun formatBody(body: String, contentType: String?): String { 13 | return when { 14 | contentType?.contains("json", true) == true -> formatJson(body) 15 | contentType?.contains("xml", true) == true -> formatXml(body) 16 | else -> body 17 | } 18 | } 19 | 20 | private fun formatJson(json: String): String { 21 | return GsonHelper.setPrettyPrinting(json) 22 | } 23 | 24 | private fun formatXml(xml: String): String { 25 | return try { 26 | val serializer = SAXTransformerFactory.newInstance().newTransformer() 27 | serializer.setOutputProperty(OutputKeys.INDENT, "yes") 28 | serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2") 29 | val xmlSource = SAXSource(InputSource(ByteArrayInputStream(xml.toByteArray()))) 30 | val res = StreamResult(ByteArrayOutputStream()) 31 | serializer.transform(xmlSource, res) 32 | String((res.outputStream as ByteArrayOutputStream).toByteArray()) 33 | } catch (e: Exception) { 34 | xml 35 | } 36 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/ui/sp/SpFileAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.ui.sp 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.lygttpod.monitor.R 8 | import com.lygttpod.monitor.data.SpData 9 | import com.lygttpod.monitor.databinding.ItemSpFileBinding 10 | 11 | /** 12 | *
13 |  *      author  : Allen
14 |  *      date    : 2022/8/6
15 |  *      desc    :
16 |  * 
17 | */ 18 | class SpFileAdapter : RecyclerView.Adapter() { 19 | 20 | private var list: List = listOf() 21 | 22 | var onItemClick: ((SpData) -> Unit)? = null 23 | 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpFileViewHolder { 25 | return SpFileViewHolder( 26 | LayoutInflater.from(parent.context).inflate(R.layout.item_sp_file, parent, false) 27 | ) 28 | } 29 | 30 | override fun onBindViewHolder(holder: SpFileViewHolder, position: Int) { 31 | holder.bindData(list[position]) 32 | holder.itemView.setOnClickListener { 33 | onItemClick?.invoke(list[position]) 34 | } 35 | } 36 | 37 | override fun getItemCount() = list.size 38 | 39 | fun setData(list: List?) { 40 | this.list = list ?: listOf() 41 | notifyDataSetChanged() 42 | } 43 | 44 | inner class SpFileViewHolder(view: View) : RecyclerView.ViewHolder(view) { 45 | private val binding = ItemSpFileBinding.bind(view) 46 | 47 | fun bindData(data: SpData) { 48 | binding.tvSpFileName.text = "${data.fileName}.xml" 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /monitor/src/main/java/com/lygttpod/monitor/ui/sp/SpFileDetailAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lygttpod.monitor.ui.sp 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.lygttpod.monitor.R 8 | import com.lygttpod.monitor.data.SpSubData 9 | import com.lygttpod.monitor.databinding.ItemSpFileDetailBinding 10 | 11 | /** 12 | *
13 |  *      author  : Allen
14 |  *      date    : 2022/8/6
15 |  *      desc    :
16 |  * 
17 | */ 18 | class SpFileDetailAdapter : RecyclerView.Adapter() { 19 | 20 | private var list: List = listOf() 21 | 22 | var onItemClick: ((SpSubData) -> Unit)? = null 23 | 24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpFileDetailViewHolder { 25 | return SpFileDetailViewHolder( 26 | LayoutInflater.from(parent.context).inflate(R.layout.item_sp_file_detail, parent, false) 27 | ) 28 | } 29 | 30 | override fun onBindViewHolder(holder: SpFileDetailViewHolder, position: Int) { 31 | holder.bindData(list[position]) 32 | holder.itemView.setOnClickListener { 33 | onItemClick?.invoke(list[position]) 34 | } 35 | } 36 | 37 | override fun getItemCount() = list.size 38 | 39 | fun setData(list: List) { 40 | this.list = list 41 | notifyDataSetChanged() 42 | } 43 | 44 | inner class SpFileDetailViewHolder(view: View) : RecyclerView.ViewHolder(view) { 45 | private val binding = ItemSpFileDetailBinding.bind(view) 46 | 47 | fun bindData(data: SpSubData) { 48 | binding.tvKey.text = data.keyName 49 | binding.tvValue.text = "${data.keyValue?.value}" 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /monitor/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'kotlin-android' 4 | id 'kotlin-kapt' 5 | } 6 | 7 | android { 8 | compileSdk 28 9 | 10 | defaultConfig { 11 | minSdk 21 12 | targetSdk 28 13 | 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | kotlinOptions { 28 | jvmTarget = '1.8' 29 | } 30 | buildFeatures { 31 | viewBinding true 32 | } 33 | } 34 | 35 | dependencies { 36 | 37 | implementation 'androidx.core:core-ktx:1.1.0' 38 | implementation 'androidx.appcompat:appcompat:1.3.0' 39 | implementation 'com.google.android.material:material:1.4.0' 40 | 41 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' 42 | 43 | implementation 'com.squareup.okhttp3:okhttp:4.3.1' 44 | implementation 'com.google.code.gson:gson:2.8.6' 45 | def room_version = "2.3.0" 46 | implementation "androidx.room:room-runtime:$room_version" 47 | kapt "androidx.room:room-compiler:$room_version" 48 | implementation "androidx.room:room-ktx:$room_version" 49 | 50 | def als_version = "0.0.1" 51 | implementation "io.github.lygttpod.android-local-service:core:$als_version" 52 | implementation "io.github.lygttpod.android-local-service:annotation:$als_version" 53 | kapt "io.github.lygttpod.android-local-service:processor:$als_version" 54 | 55 | implementation 'com.github.lygttpod:ShapeView:1.0.2' 56 | 57 | } 58 | 59 | apply from: '../upload.gradle' -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 32 | 33 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | -------------------------------------------------------------------------------- /monitor/src/main/res/layout/activity_monitor_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 22 | 23 | 33 | 34 | 41 | 42 | 45 | 46 | 57 | 58 | 69 | 70 | 81 | 82 | 93 | 94 | 106 | 107 | 115 | 116 | 127 | 128 | 138 | 139 | 149 | 150 | 151 | 159 | 160 | 169 | 170 | 182 | 183 | 192 | 193 | 203 | 204 | 211 | 212 | 213 | 214 | 225 | 226 | 237 | 238 | 250 | 251 | 258 | 259 | 273 | 274 | 282 | 283 | 298 | 299 | 309 | 310 | 311 | 319 | 320 | 335 | 336 | 344 | 345 | 361 | 362 | 363 | 364 | 365 | --------------------------------------------------------------------------------