第三方-DoraemonKit

README-CN

Android接入指南

由于jcenter事件的影响,我们需要将DoKit For Android迁移到mavenCentral(),但是需要更改groupId.所以大家要注意一下,具体的更新信息如下:

lastversion:3.5.0kotlin编译插件为1.4.32 ;支持Gradle 6.8及以上

lastversion:3.5.0.1kotlin编译插件为1.3.72; 支持Gradle 6.8及以下

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

${aarName}需要改为指定的名称,参考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//核心模块

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 模块

releaseImplementation "io.github.didi.dokit:dokitx-no-op:${lastversion}"

debugImplementation 需要根据自己的构建改成对应的productFlavor

下面所有的例子均用dokitx举例。要使用support版本请将dokitx改为dokit即可。 v3.3.5以后的版本需要添加mavenCentral()仓库

接入步骤

1. Gradle 依赖

1
2
3
4
5
6
dependencies {

debugImplementation 'io.github.didi.dokit:dokitx:${lastversion}'
releaseImplementation 'io.github.didi.dokit:dokitx-no-op:${lastversion}'

}

滴滴内部业务:

滴滴内部业务线接入请添加模块

1
2
3
debugImplementation 'io.github.didi.dokit:dokitx-rpc:${lastversion}'
//一机多控内部网络库支持
debugImplementation 'io.github.didi.dokit:dokitx-rpc-mc:${lastversion}'

最新版本参见这里

2. 初始化

在 App 启动的时候进行初始化。

1
2
3
4
5
6
7
8
@Override
public void onCreate() {

DoKit.Builder(this)
.productId("需要使用平台功能的话,需要到dokit.cn平台申请id")
.build()

}

3. 流量监控以及其他AOP功能(可选)

AOP包括以下几个功能: 1)百度、腾讯、高德地图的经纬度模拟 2)UrlConnection、Okhttp 抓包以及后续的接口hook功能 3)App 启动耗时统计 4)慢函数 5)大图

在项目的 build.gradle 中添加 classpath。

1
2
3
4
5
6
7
buildscript {
dependencies {

classpath 'io.github.didi.dokit:dokitx-plugin:${lastversion}'

}
}

在 app 的 build.gradle 中添加 plugin。

1
apply plugin: 'com.didi.dokit'

插件配置选项: 添加到app module 的build.gradle文件下 与android {}处于同一级

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
dokitExt {
//通用设置
comm {
//地图经纬度开关
gpsSwitch true
//网络开关
networkSwitch true
//大图开关
bigImgSwitch true
//webView js 抓包
webViewSwitch true
}

slowMethod {
//调用栈模式配置 对应gradle.properties中DOKIT_METHOD_STRATEGY=0
stackMethod {
//默认值为 5ms 小于该值的函数在调用栈中不显示
thresholdTime 10
//调用栈函数入口 千万不要用我默认的配置 如果有特殊需求修改成项目中自己的入口 假如不需要可以去掉该字段
enterMethods = ["com.didichuxing.doraemondemo.MainDebugActivity.test1"]
//黑名单 粒度最小到类 暂不支持到方法 千万不要用我默认的配置 如果有特殊需求修改成项目中自己的入口 假如不需要可以去掉该字段
methodBlacklist = ["com.facebook.drawee.backends.pipeline.Fresco"]
}
//普通模式配置 对应gradle.properties中DOKIT_METHOD_STRATEGY=1
normalMethod {
//默认值为 500ms 小于该值的函数在运行时不会在控制台中被打印
thresholdTime 500
//需要针对函数插装的包名 千万不要用我默认的配置 如果有特殊需求修改成项目中自己的项目包名 假如不需要可以去掉该字段
packageNames = ["com.didichuxing.doraemondemo"]
//不需要针对函数插装的包名&类名 千万不要用我默认的配置 如果有特殊需求修改成项目中自己的项目包名 假如不需要可以去掉该字段
methodBlacklist = ["com.didichuxing.doraemondemo.dokit"]
}
}
}

其中strategymethodSwitch配置项已经弃用。新的配置开关位于项目根目录下的gradle.properties中。

具体的配置如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// dokit全局配置
// 插件开关
DOKIT_PLUGIN_SWITCH=true
// DOKIT读取三方库会和booster冲突 如果你的项目中也集成了booster 建议将开关改成false
DOKIT_THIRD_LIB_SWITCH=true
// 插件日志
DOKIT_LOG_SWITCH=true
// 自定义Webview的全限定名 主要是作用于h5 js抓包和数据mock
DOKIT_WEBVIEW_CLASS_NAME=com/didichuxing/doraemonkit/widget/webview/MyWebView
// dokit 慢函数开关
DOKIT_METHOD_SWITCH=true
// dokit 函数调用栈层级
DOKIT_METHOD_STACK_LEVEL=4
// 0:默认模式 打印函数调用栈 需添加指定入口 默认为application onCreate 和attachBaseContext
// 1:普通模式 运行时打印某个函数的耗时 全局业务代码函数插入
DOKIT_METHOD_STRATEGY=0

理由: 为了减少项目的编译时间,所以慢函数的默认开关为false。再加上plugin的transform注册必须早于project.afterEvaluate。所以无法通过原先的配置项拿到配置信息,只能通过在全局的gradle.properties中的配置可以拿到。

tips: 当修改完DoKit插件的相关配置以后一定要clean一下重新编译才能生效。这是AS的缓存增量编译导致的,暂时没有其他好的解决方案。

4. 自定义功能组件(可选)

自定义组件需要实现 IKit 接口,该接口对应哆啦A梦功能面板中的组件。

以代驾乘客端为例,实现环境切换组件如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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?) {
}
}

在初始化的时候注册自定义组件。

1
2
3
4
5
6
7
override fun onCreate() {
DoKit.Builder(this)
.productId("需要使用平台功能的话,需要到dokit.cn平台申请id")
.customKits(mapKits)
.build()

}

DoKit入口api

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
public class DoKit private constructor() {
companion object {



/**
* 主icon是否处于显示状态
*/
@JvmStatic
val isMainIconShow: Boolean
get() = false


/**
* 显示主icon
*/
@JvmStatic
fun show() {
}

/**
* 直接显示工具面板页面
*/
@JvmStatic
fun showToolPanel() {
}

/**
* 直接隐藏工具面板
*/
@JvmStatic
fun hideToolPanel() {
}

/**
* 隐藏主icon
*/
@JvmStatic
fun hide() {
}

/**
* 启动悬浮窗
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
@JvmOverloads
fun launchFloating(
targetClass: Class<out AbsDokitView>,
mode: DoKitViewLaunchMode = DoKitViewLaunchMode.SINGLE_INSTANCE,
bundle: Bundle? = null
) {
}


/**
* 启动悬浮窗
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
@JvmOverloads
fun launchFloating(
targetClass: KClass<out AbsDokitView>,
mode: DoKitViewLaunchMode = DoKitViewLaunchMode.SINGLE_INSTANCE,
bundle: Bundle? = null
) {
}

/**
* 移除悬浮窗
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
fun removeFloating(targetClass: Class<out AbsDokitView>) {
}

/**
* 移除悬浮窗
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
fun removeFloating(targetClass: KClass<out AbsDokitView>) {
}

/**
* 移除悬浮窗
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
fun removeFloating(dokitView: AbsDokitView) {
}


/**
* 启动全屏页面
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
@JvmOverloads
fun launchFullScreen(
targetClass: Class<out BaseFragment>,
context: Context? = null,
bundle: Bundle? = null,
isSystemFragment: Boolean = false
) {
}

/**
* 启动全屏页面
* @JvmStatic:允许使用java的静态方法的方式调用
* @JvmOverloads :在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
*/
@JvmStatic
@JvmOverloads
fun launchFullScreen(
targetClass: KClass<out BaseFragment>,
context: Context? = null,
bundle: Bundle? = null,
isSystemFragment: Boolean = false
) {
}


@JvmStatic
fun <T : AbsDokitView> getDoKitView(
activity: Activity,
clazz: Class<out T>
): T? {
return null
}

@JvmStatic
fun <T : AbsDokitView> getDoKitView(
activity: Activity,
clazz: KClass<out T>
): T? {
return null
}

/**
* 发送自定义一机多控事件
*/
@JvmStatic
fun sendCustomEvent(
eventType: String,
view: View? = null,
param: Map<String, String>? = null
) {
}
}


class Builder(private val app: Application) {
private var productId: String = ""
private var mapKits: LinkedHashMap<String, List<AbstractKit>> = linkedMapOf()
private var listKits: List<AbstractKit> = arrayListOf()

init {
}

fun productId(productId: String): Builder {
return this
}

/**
* mapKits & listKits 二选一
*/
fun customKits(mapKits: LinkedHashMap<String, List<AbstractKit>>): Builder {
return this
}

/**
* mapKits & listKits 二选一
*/
fun customKits(listKits: List<AbstractKit>): Builder {
return this
}

/**
* H5任意门全局回调
*/
fun webDoorCallback(callback: WebDoorManager.WebDoorCallback): Builder {
return this
}

/**
* 禁用app信息上传开关,该上传信息只为做DoKit接入量的统计,如果用户需要保护app隐私,可调用该方法进行禁用
*/
fun disableUpload(): Builder {
return this
}

fun debug(debug: Boolean): Builder {
return this
}

/**
* 是否显示主入口icon
*/
fun alwaysShowMainIcon(alwaysShow: Boolean): Builder {
return this
}

/**
* 设置加密数据库密码
*/
fun databasePass(map: Map<String, String>): Builder {
return this
}

/**
* 设置文件管理助手http端口号
*/
fun fileManagerHttpPort(port: Int): Builder {
return this
}

/**
* 一机多控端口号
*/
fun mcWSPort(port: Int): Builder {
return this
}

/**
* 一机多控自定义拦截器
*/
fun mcClientProcess(interceptor: McClientProcessor): Builder {
return this
}

/**
*设置dokit的性能监控全局回调
*/
fun callBack(callback: DoKitCallBack): Builder {
return this
}


/**
* 设置扩展网络拦截器的代理对象
*/
fun netExtInterceptor(extInterceptorProxy: DokitExtInterceptor.DokitExtInterceptorProxy): Builder {
return this
}


fun build() {
}
}
}

5. FAQ

参考这里

Android

1、为什么接入后看不到悬浮窗入口?

先确认是否打开应用的悬浮窗权限,同时确认是否错误引用no-op版本。

2、 com.didichuxing.doraemonkit:kitcom.didichuxing.doraemonkit:kit-no-op有什么区别?

no-op版本提供空实现,DoraemonKit不推荐集成到线上版本使用的,可通过gradle配置动态切换正常版本和no-op版本。

3、 流量监控无数据

目前流量监测功能只支持OkHttp3和HttpUrlConnection的自动注入,其他网络库暂不支持。 其他网络库可以使用NetworkPrinterHelper类进行请求数据的手动注入,使用参考demo。

4、 性能监控中,CPU、RAM无数据

旧版本SDK的CPU监控实现在8.0系统读取不到数据。新版本已修改实现方式,可以正常读取。

5、 帧率、CPU、RAM数据不准确

由于读取cpu、内存数据本身需要消耗cpu和内存,加上心跳图绘制需要消耗性能,所以开启这几项功能后,数据比app实际使用值有升高。

6、 com.hujiang.aspectjx:gradle-android-plugin-aspectjx是否必须?

注意:该插件只在低版本的dokit sdk中采用,新版本已经替换为ASM的技术方案,可以去掉。

这个插件的用处是在编译阶段在okhttp和httpurlconnection的调用处进行插桩,用来收集网络请求数据从而实现流量监控功能,如果不需要流量监控功能或者使用的是非okhttp和httpurlconnection网络库,可以不引用这个插件。 因为这个插件会涉及到字节码的修改,同时会插入一些代码到网络请求中,对性能和稳定性有影响,所以非常不推荐在线上版本中使用。在线上版本中,务必去除该插件的引用。

7、 沙盒游览功能能否打开数据库、sp文件?

目前已经支持

8、为什么地图的经纬度 hook 不成功

请检查是否集成了dokit-plugin插件

9、dokit 的数据mock以及健康体检到需要依赖dokit-plugin。

请检查是否集成了dokit-plugin插件

10、拾色器功能失效。

请先检查你当前app的targetSdkVersion是否大于等于29(Android Q).

1)假如你的app没有针对Android Q进行适配,可以考虑将targetSdkVersion设置为小于29即可。

2)我当前app的功能已经针对Android Q进行适配,想要正常使用拾色器。你可以添加以下代码到你项目的AndroidManifest.xml中。**(线上真实版本记得一定要去掉以下代码,dokit的所有功能只在开发环境中使用,千万不要带到线上)**

1
2
3
4
5
<service
android:name="com.didichuxing.doraemonkit.kit.colorpick.ScreenRecorderService"
android:enabled="true"
android:foregroundServiceType="mediaProjection"
tools:targetApi="q" />

如果编译过程中报找不到foregroundServiceType属性,请检查你项目的compileSdkVersion是否已经设置为29.一般情况下targetSdkVersion总是小于或等于compileSdkVersion。

原理: 因为Android Q针对屏幕截图的权限进行了调整。假如你项目的targetSdkVersion设置为29,系统会要求你的截图操作必须在前台服务中进行操作。否则无法正常进行屏幕截图。

11、Android Dokit为什么迟迟不升级成Androidx

其实现阶段Dokit的所有功能都是只支持在开发阶段,所以就意味着dokit依赖库所依赖的所有第三方库都不会带到线上,于此同时dokit-no-op中没有依赖任何第三方库,并且所有入口方法都是空实现。开发者根本不用担心线上包变大或者依赖冲突等问题。所以Android端现阶段升级Androidx的意义并不是很大。

12、大图检测功能未生效

当前安卓平台只支持glide4.0+、fresco、picasso、Imageloader 4个图片框架的自动检测。 当fileSize显示为0的时候,有可能是你设置了图片缓存,所以请请你一下缓存再重试。fileSize只会在通过网络加载时才会拦截。

13、编译demo失败

1、确认你的androidStudio版本时候升级到3.6.0及以上,因为项目中使用到了databind 2、去除和doraemonkit-rpc相关的引入,主要存在setting文件和build.gradle中,因为该module中使用滴滴自己的网络库外部并不能下载。

14、dokit版本的问题

|DoKit|最新版本|描述| |-|-|-|-| |支持Androidx|3.1.6|从v3.1.0版本开始支持androidx |支持android support|3.0.7.1|support 支持还会维护一到两个版本,请大家尽快拥抱androidx吧

15、数据mock不成功

1、当前dokit的数据mock逻辑为实际的接口path+query 必须包含在平台端配置的path+query 否则会匹配不到 2、如果你的项目中使用了retrofit,请确认你的okhttp版本时候大于3.14.0,如果是请把版本版本降低到3.12.1。参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
app module的build.gradle下添加以下代码

configurations.all {
resolutionStrategy.eachDependency { details ->

if (details.requested.group == 'com.squareup.okhttp3'
&& details.requested.name == 'okhttp') {
details.useVersion "3.12.1"
}
}
}

15、编译异常

项目编译过程中出现以下异常信息:

1
Cause: tried to access method com.google.common.io.Files.fileTreeTraverser()Lcom/google/common/collect/TreeTraverser; from class com.android.utils.FileUtils

请将AGP(AndroidStudio Gradle Plugin)版本升级3.3.0以上