ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DoKit Android 接入指南:从 Gradle 依赖、AOP 插件到自定义组件的完整实践

DoKit Android 接入指南:从 Gradle 依赖、AOP 插件到自定义组件的完整实践 DoKit Android 接入指南从 Gradle 依赖、AOP 插件到自定义组件的完整实践【免费下载链接】DoKit一款面向泛前端产品研发全生命周期的效率平台。项目地址: https://gitcode.com/gh_mirrors/do/DoKit导读本文基于 DoKit原 DoraemonKit开源仓库中的 Android 接入指南系统讲解在 Android 工程中接入 DoKit 调试工具的完整流程包括版本与仓库选型、Gradle 依赖接入、App 启动初始化、基于字节码插桩的 AOP 插件流量监控、慢函数、大图检测、WebView 抓包等、自定义功能组件IKit的注册方式以及 DoKit 入口 API 的常用能力。文中所有配置与代码均对应仓库内的真实实现读者按步骤操作即可在自己的 Android 项目中集成 DoKit并理解其底层运行机制。说明DoKit 的 Android 端由多个 Gradle 模块组成模块名与发布 Artifact 的对应关系定义在 dokit_module.json 中例如dokit→dokitx、dokit-no-op→dokitx-no-op、dokit-plugin→dokitx-plugin。下文所述以 dokitx 为例即指核心模块的 AndroidX 版本。一、版本与仓库选型先搞清楚你该用哪个版本由于 jcenter 事件的影响DoKit For Android 已迁移到mavenCentral()仓库groupId 同时发生了变更因此接入前必须先根据自身环境确认版本号与依赖坐标。1.1 版本对应关系总览| DoKit 版本 | 依赖坐标示例 | 描述 | | - | - | - | | 3.3.5 及以后的 AndroidX |debugImplementation io.github.didi.dokit:${aarName}:${lastversion}| (1) dokitx 的 library 和 plugin 的 groupId 及版本号需要保持一致(2) AGP 最低版本要求 3.3.0 | | 3.3.5 及以前的 AndroidX |debugImplementation com.didichuxing.doraemonkit:${aarName}:3.3.5| (1) dokitx 的 library 和 plugin 的 groupId 及版本号需要保持一致(2) AGP 最低版本要求 3.3.0 | | 支持 Android support |debugImplementation com.didichuxing.doraemonkit:${aarName}:3.3.5| support 版本放弃更新请尽快升级和适配 AndroidX |其中lastversion有两套分支lastversion: 3.5.0kotlin 编译插件为 1.4.32支持 Gradle 6.8 及以上lastversion: 3.5.0.1kotlin 编译插件为 1.3.72支持 Gradle 6.8 及以下。从仓库 config.gradle 中可以看到DoKit 本身维护了kotlin_version_v13 1.3.72与kotlin_version_v14 1.4.32两套 Kotlin 版本并通过needKotlinV14方法根据发布版本是否包含kotlin-13后缀来决定使用哪一套这正是上述双分支版本的实现来源。1.2${aarName}与核心模块的完整对照${aarName}需要替换为实际的模块名称。核心模块列表如下// 核心模块 debugImplementation io.github.didi.dokit:dokitx:${lastversion} // 文件同步模块 debugImplementation io.github.didi.dokit:dokitx-ft:${lastversion} // 一机多控模块 debugImplementation io.github.didi.dokit:dokitx-mc:${lastversion} // weex 模块 debugImplementation io.github.didi.dokit:dokitx-weex:${lastversion} // no-op 模块release 包使用 releaseImplementation io.github.didi.dokit:dokitx-no-op:${lastversion}补充说明debugImplementation 需要根据自己工程的构建类型改成对应的 productFlavor即若你的调试构建是某个自定义 flavor应将debugImplementation替换为该 flavor 对应的 configuration下文所有例子均以dokitx举例要使用 support 版本只需把dokitx改为dokit即可v3.3.5 以后的版本需要在工程中显式添加mavenCentral()仓库。二、接入步骤2.1 第 1 步添加 Gradle 依赖在 app module 的build.gradle中声明依赖dependencies { debugImplementation io.github.didi.dokit:dokitx:${lastversion} releaseImplementation io.github.didi.dokit:dokitx-no-op:${lastversion} }这里dokitx-no-op是 DoKit 的空实现模块no-op。从仓库中 dokit-no-op 的 DoKit 入口实现 可以看到它保留了与正式模块完全一致的DoKit类、Builder及全部方法签名但所有方法体均为空实现例如show()、launchFloating()等方法内部什么都不做。这样做的目的是release 包中不包含任何 DoKit 的调试逻辑同时业务代码无需任何改动即可正常编译运行。滴滴内部业务线使用滴滴内部网络库的场景还需要额外添加两个模块// 数据 mock 内部网络库支持 debugImplementation io.github.didi.dokit:dokitx-rpc:${lastversion} // 一机多控内部网络库支持 debugImplementation io.github.didi.dokit:dokitx-rpc-mc:${lastversion}2.2 第 2 步App 启动时初始化在Application.onCreate中完成初始化override fun onCreate() { DoKit.Builder(this) .productId(需要使用平台功能的话需要到 dokit.cn 平台申请 id) .build() }从源码看DoKit.Builder的init块会先执行DoKitEnv.app app完成 Application 环境注入最终build()会调用DoKitReal.install(app, mapKits, listKits, productId)完成真正的安装见 DoKit.kt。Builder还提供了丰富的可选配置常见的有DoKit.Builder(this) .productId(...) // mapKits 与 listKits 二选一注册自定义功能组件 .customKits(mapKits) // H5 任意门全局回调 .webDoorCallback(callback) // 禁用 app 信息上传该上传仅用于 DoKit 接入量统计需要保护隐私可调用 .disableUpload() // 是否总是显示主入口 icon .alwaysShowMainIcon(true) // 设置加密数据库密码Map库名, 密码 .databasePass(map) // 设置文件管理助手 http 端口号 .fileManagerHttpPort(port) // 一机多控端口号 .mcWSPort(port) // 一机多控自定义拦截器 .mcClientProcess(interceptor) // 设置性能监控全局回调 .callBack(callback) // 设置扩展网络拦截器的代理对象 .netExtInterceptor(proxy) .build()2.3 第 3 步流量监控及其他 AOP 功能可选DoKit 的 AOP 能力基于字节码插桩实现包括以下功能百度、腾讯、高德地图的经纬度模拟UrlConnection、OkHttp抓包以及后续的接口 hook 功能App 启动耗时统计慢函数大图检测。先在项目根目录的build.gradle中添加 classpathbuildscript { dependencies { classpath io.github.didi.dokit:dokitx-plugin:${lastversion} } }再在app module的build.gradle中应用插件apply plugin: com.didi.dokit注意dokitx 的 library 与 plugin 的 groupId 及版本号必须保持一致且 AGP 最低版本要求 3.3.0。2.3.1 插件配置选项dokitExt插件配置块dokitExt需要添加到 app module 的build.gradle下与android {}处于同一级dokitExt { //通用设置 comm { //地图经纬度开关 gpsSwitch true //网络开关 networkSwitch true //大图开关 bigImgSwitch true //webView js 抓包 webViewSwitch true } slowMethod { //调用栈模式配置 对应 gradle.properties 中 DOKIT_METHOD_STRATEGY0 stackMethod { //默认值为 5ms小于该值的函数在调用栈中不显示 thresholdTime 10 //调用栈函数入口示例配置实际使用请换成项目自己的入口不需要可去掉该字段 enterMethods [com.didichuxing.doraemondemo.MainDebugActivity.test1] //黑名单粒度最小到类暂不支持到方法示例配置实际使用请换成项目自己的入口不需要可去掉该字段 methodBlacklist [com.facebook.drawee.backends.pipeline.Fresco] } //普通模式配置 对应 gradle.properties 中 DOKIT_METHOD_STRATEGY1 normalMethod { //默认值为 500ms小于该值的函数在运行时不会在控制台中被打印 thresholdTime 500 //需要针对函数插装的包名示例配置实际使用请换成项目自己的包名不需要可去掉该字段 packageNames [com.didichuxing.doraemondemo] //不需要针对函数插装的包名类名示例配置实际使用请换成项目自己的包名不需要可去掉该字段 methodBlacklist [com.didichuxing.doraemondemo.dokit] } } }参数含义速查| 配置项 | 所属块 | 含义 | 默认值 | | - | - | - | - | |gpsSwitch|comm| 地图经纬度模拟开关 | true示例 | |networkSwitch|comm| 网络抓包开关 | true示例 | |bigImgSwitch|comm| 大图检测开关 | true示例 | |webViewSwitch|comm| WebView JS 抓包开关 | true示例 | |thresholdTime|stackMethod| 调用栈模式下小于该值的函数不显示 | 5ms | |enterMethods|stackMethod| 调用栈函数入口列表 | 无 | |methodBlacklist|stackMethod| 黑名单粒度最小到类 | 无 | |thresholdTime|normalMethod| 普通模式下小于该值的函数不打印 | 500ms | |packageNames|normalMethod| 需要插装的包名列表 | 无 | |methodBlacklist|normalMethod| 不参与插装的包名/类名 | 无 |2.3.2 新版全局开关gradle.properties其中strategy和methodSwitch配置项已经弃用。新的配置开关位于项目根目录下的gradle.properties中具体配置如下// dokit 全局配置 // 插件开关 DOKIT_PLUGIN_SWITCHtrue // DOKIT 读取三方库会和 booster 冲突如果你的项目中也集成了 booster建议将开关改成 false DOKIT_THIRD_LIB_SWITCHtrue // 插件日志 DOKIT_LOG_SWITCHtrue // 自定义 Webview 的全限定名主要是作用于 h5 js 抓包和数据 mock DOKIT_WEBVIEW_CLASS_NAMEcom/didichuxing/doraemonkit/widget/webview/MyWebView // dokit 慢函数开关 DOKIT_METHOD_SWITCHtrue // dokit 函数调用栈层级 DOKIT_METHOD_STACK_LEVEL4 // 0: 默认模式 打印函数调用栈需添加指定入口默认为 application onCreate 和 attachBaseContext // 1: 普通模式 运行时打印某个函数的耗时全局业务代码函数插入 DOKIT_METHOD_STRATEGY0从源码看这些开关确实是在插件执行时从 Gradle 属性中读取的DoKitPlugin.kt中通过project.getProperty(DOKIT_PLUGIN_SWITCH, true)、project.getProperty(DOKIT_METHOD_STRATEGY, 0)、project.getProperty(DOKIT_THIRD_LIB_SWITCH, true)等读取全局配置见 DoKitPlugin.kt并写入DoKitExtUtil供后续 Transform 处理使用。为什么把开关放在 gradle.properties 而不是插件 DSL 中官方给出的理由是为了减少项目的编译时间慢函数的默认开关为 false再加上 plugin 的 transform 注册必须早于project.afterEvaluate因此无法通过原先的配置项拿到配置信息只能通过在全局gradle.properties中的配置获取。Tips当修改完 DoKit 插件的相关配置以后一定要 clean 一下重新编译才能生效。这是 AS 的缓存增量编译导致的暂时没有其他好的解决方案。2.3.3 开启插件调试如需调试插件本身可以带调试参数运行 Gradle 任务./gradlew :app:assembleDebug -Dorg.gradle.daemonfalse -Dorg.gradle.debugtrue2.4 第 4 步自定义功能组件可选自定义组件需要实现IKit接口该接口对应哆啦A梦功能面板中的组件。从源码看IKit定义在 IKit.kt包含category分类、name名称资源 id、icon图标资源 id、onClick已废弃用onClickWithReturn代替、onClickWithReturn(activity)点击回调返回true隐藏面板false不隐藏以及onAppInit(context)app 初始化时调用。官方推荐直接继承AbstractKit见 AbstractKit.kt它以默认实现兜底了IKit的大部分抽象方法并额外提供了startUniversalActivity启动全屏页面、currentActivity()获取栈顶 Activity等便捷方法还声明了canShow是否显示在工具面板上、innerKitId()内置工具 ID等扩展能力。以代驾乘客端为例实现一个环境切换组件class DemoKit : AbstractKit() { override val category: Int get() Category.BIZ override val name: Int get() R.string.dk_kit_demo override val icon: Int get() R.mipmap.dk_sys_info override fun onClickWithReturn(activity: Activity): Boolean { SimpleDoKitStarter.startFloating(DemoDokitView::class.java) return true } override fun onAppInit(context: Context?) { } }关于category的取值仓库中的 Category.java 已标注Deprecated保留是为了兼容以前的 API但仍是自定义组件常用的分类常量来源BIZ 0业务模块、TOOLS 1常用工具模块、PERFORMANCE 2性能监控模块、UI 3视觉工具模块、PLATFORM 4平台工具模块等。AbstractKit中category的默认实现也声明为已废弃重不重写都不影响功能。在初始化的时候注册自定义组件override fun onCreate() { DoKit.Builder(this) .productId(需要使用平台功能的话需要到 dokit.cn 平台申请 id) .customKits(mapKits) .build() }其中customKits支持两种形式二选一customKits(mapKits: LinkedHashMapString, ListAbstractKit)按分类分组注册customKits(listKits: ListAbstractKit)平铺列表注册。2.5 DoKit 入口 APIDoKit是单例式的入口类常用 API 如下Java 侧可通过JvmStatic以静态方法方式调用带默认参数的方法配合JvmOverloads会自动暴露多个重载// 主 icon 是否处于显示状态 DoKit.isMainIconShow // 显示主 icon DoKit.show() // 直接显示工具面板页面 DoKit.showToolPanel() // 直接隐藏工具面板 DoKit.hideToolPanel() // 隐藏主 icon DoKit.hide() // 启动悬浮窗默认单实例模式可携带 bundle 参数 DoKit.launchFloating(targetClass, DoKitViewLaunchMode.SINGLE_INSTANCE, bundle) // 移除悬浮窗 DoKit.removeFloating(targetClass) // 启动全屏页面可指定是否为系统内置 fragment DoKit.launchFullScreen(targetClass, context, bundle, isSystemFragment) // 获取当前 Activity 上的 DoKitView 实例 DoKit.getDoKitView(activity, clazz) // 发送自定义一机多控事件 DoKit.sendCustomEvent(eventType, view, param) // 获取一机多控类型 DoKit.mcMode()以launchFloating为例其 Kotlin 实现直接委托给DoKitReal.launchFloating(targetClass, mode, bundle)并额外提供了inline fun reified T : AbsDoKitView launchFloating(mode, bundle)这种免传 Class 的便捷写法方便在业务代码中快速唤起自定义悬浮窗见 DoKit.kt。2.6 FAQ更多接入过程中的常见问题可参考仓库文档 Doc/android-ReleaseNotes.mdAndroid 版本发布记录以及 Doc/iOS_cn_guide.md跨端能力说明。常见问题一般集中在仓库未配置mavenCentral()、library 与 plugin 版本号不一致、修改插件配置后未 clean 重新编译、release 包误引入dokitx而非dokitx-no-op等均可对照上文各步骤逐一排查。三、深入理解接入背后的模块化设计DoKit Android 端采用核心模块 能力模块 no-op 占位的模块化设计这一点从 dokit_module.json 与 config.gradle 中可以得到完整印证核心模块dokit发布为dokitx包含工具面板、悬浮窗、网络监控、性能监控、视觉工具等全部内置能力能力模块dokitx-ft文件同步、dokitx-mc一机多控、dokitx-weexWeex 调试、dokitx-leakcanary内存泄漏检测、dokitx-gps-mockGPS 模拟等按需引入避免包体膨胀no-op 模块dokit-no-op发布为dokitx-no-op提供与核心模块一致的 API 空实现供 release 构建占位实现debug 有工具、release 零成本的经典接入模式编译插件dokit-plugin发布为dokitx-plugin以 Transform 方式完成字节码插桩负责流量监控、慢函数、大图等 AOP 能力配置集中在 buildSrc 插件源码。这种设计使得接入方可以只依赖自己需要的模块同时通过debugImplementation/releaseImplementation的构建配置天然隔离调试代码与线上代码是 DoKit 在 Android 侧接入体验的核心保证。四、总结接入 DoKit Android 端的核心要点可归纳为四步选版本mavenCentral 双分支 lastversion→ 加依赖dokitx dokitx-no-op→ 初始化DoKit.Builder→ 按需开启 AOP 与自定义组件。版本选择上注意 3.3.5 是 groupId 变更的分水岭AOP 能力依赖dokitx-plugin与gradle.properties全局开关修改后必须 clean 重新编译自定义组件继承AbstractKit后通过customKits注册即可出现在工具面板。掌握以上要点即可快速将 DoKit 的调试能力集成进自己的 Android 工程并在 debug/release 双构建下保持业务代码零侵入。【免费下载链接】DoKit一款面向泛前端产品研发全生命周期的效率平台。项目地址: https://gitcode.com/gh_mirrors/do/DoKit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表