提交 082545a5 编写于 作者: 囧jt's avatar 囧jt

modify:

[Android]: 一机多控平台端联调
上级 0b1bb280
......@@ -89,7 +89,8 @@ class App : Application() {
DoKit.Builder(this)
.productId("749a0600b5e48dd77cf8ee680be7b1b7")
//.productId("749a0600b5e48dd77cf8ee680be7b1b7")
.productId("277016abcc33bff1e6a4f1afdf14b8e1")
.disableUpload()
.customKits(mapKits)
.fileManagerHttpPort(9001)
......
......@@ -218,7 +218,14 @@ class MainDebugActivityOkhttpV3 : BaseActivity(), View.OnClickListener,
jsonObject.put("d", "dd")
OkGo.post<String>("https://wanandroid.com/user_article/list/0/json?b=bb&a=aa")
.upJson(jsonObject)
.execute()
.execute(object : StringCallback() {
override fun onSuccess(response: Response<String>?) {
response?.let {
Log.i(TAG, "okhttp====onSuccess===>" + it.body())
}
}
})
// OkGo.post<String>("https://wanandroid.com/user_article/list/0/json?b=bb&a=aa")
......
......@@ -6,13 +6,15 @@ import com.didichuxing.doraemonkit.extension.doKitGlobalScope
import com.didichuxing.doraemonkit.extension.sortedByKey
import com.didichuxing.doraemonkit.extension.toMap
import com.didichuxing.doraemonkit.kit.mc.all.McConstant
import com.didichuxing.doraemonkit.kit.mc.data.HttpMatchedInfo
import com.didichuxing.doraemonkit.kit.mc.data.HttpUploadInfo
import com.didichuxing.doraemonkit.kit.network.NetworkManager
import com.didichuxing.doraemonkit.kit.network.okhttp.InterceptorUtil
import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.AbsDoKitInterceptor
import com.didichuxing.doraemonkit.util.EncodeUtils
import com.didichuxing.doraemonkit.util.GsonUtils
import com.didichuxing.doraemonkit.util.LogHelper
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.*
import okio.ByteString
import java.net.URLDecoder
......@@ -34,6 +36,7 @@ class DokitMcInterceptor : AbsDoKitInterceptor() {
val response = chain.proceed(request)
val url = request.url()
val host: String = url.host()
val scheme = url.scheme()
val contentType = response.header("Content-Type") ?: response.header("content-type")
//如果是图片则不进行拦截
if (InterceptorUtil.isImg(contentType)) {
......@@ -43,6 +46,15 @@ class DokitMcInterceptor : AbsDoKitInterceptor() {
if (host.equals(NetworkManager.MOCK_HOST, ignoreCase = true)) {
return response
}
if ("$scheme://$host".equals(McHttpManager.host, ignoreCase = true)) {
val strResponseBody = response.peekBody(Long.MAX_VALUE).string()
LogHelper.i(TAG, "========DoKit SDK 接口数据 Start url:$url ========")
LogHelper.json(TAG, strResponseBody)
LogHelper.i(TAG, "========DoKit SDK 接口数据 End url:$url ========")
return response
}
//不包含query字段
val method = request.method()
val path = URLDecoder.decode(url.encodedPath(), "utf-8")
......@@ -59,6 +71,9 @@ class DokitMcInterceptor : AbsDoKitInterceptor() {
val requestBodyMap = createRequestBodyMap(request)
val strRequestBody = GsonUtils.toJson(requestBodyMap)
val strResponseBody = response.peekBody(Long.MAX_VALUE).string()
LogHelper.i(TAG, "========业务接口 Start url:$url ========")
LogHelper.json(TAG, strResponseBody)
LogHelper.i(TAG, "========业务接口 End url:$url ========")
val k =
"method=$method&path=$path&fragment=$fragment&query=$strQuery&contentType=$requestContentType&requestBody=$strRequestBody"
val key = ByteString.encodeUtf8(k).md5().hex()
......@@ -68,7 +83,7 @@ class DokitMcInterceptor : AbsDoKitInterceptor() {
// val responseBody4Base64 = String(EncodeUtils.base64Encode(strResponseBody))
//todo: 实时发送网络请求
doKitGlobalScope.launch {
val httInfo = HttpInfo(
val httInfo = HttpUploadInfo(
DoKitConstant.PRODUCT_ID,
McConstant.MC_CASE_ID,
key,
......@@ -92,19 +107,34 @@ class DokitMcInterceptor : AbsDoKitInterceptor() {
}
WSMode.HOST,
WSMode.CLIENT -> {
if (McHttpManager.mHttpInfoMap[key] != null) {
val responseBodyBytes =
EncodeUtils.base64Decode(McHttpManager.mHttpInfoMap[key]?.responseBody4base64)
val responseBody =
ResponseBody.create(response.body()?.contentType(), responseBodyBytes)
return response.newBuilder()
.code(response.code())
.request(request)
.message(response.message())
.protocol(response.protocol())
.headers(response.headers())
.body(responseBody)
.build()
if (McConstant.MC_CASE_ID.isNotBlank() && DoKitConstant.PRODUCT_ID.isNotBlank()) {
//将挂起函数转为阻塞调用 等待协程返回值
return runBlocking {
try {
val result = McHttpManager.httpMatch<HttpMatchedInfo>(key)
if (result.code == McHttpManager.RESPONSE_OK && result.data != null) {
val responseBody =
ResponseBody.create(
response.body()?.contentType(),
result.data!!.responseBody
)
return@runBlocking response.newBuilder()
.code(response.code())
.request(request)
.message(response.message())
.protocol(response.protocol())
.headers(response.headers())
.body(responseBody)
.build()
} else {
return@runBlocking response
}
} catch (e: Exception) {
LogHelper.e(TAG, "e===>${e.message}")
return@runBlocking response
}
}
}
}
else -> {
......
......@@ -4,13 +4,13 @@ import com.android.volley.Request
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.StringRequest
import com.didichuxing.doraemonkit.constant.DoKitConstant
import com.didichuxing.doraemonkit.kit.mc.all.McConstant
import com.didichuxing.doraemonkit.kit.mc.all.ui.McCaseInfoDialogProvider
import com.didichuxing.doraemonkit.kit.mc.all.ui.data.McCaseInfo
import com.didichuxing.doraemonkit.kit.mc.all.ui.data.McResInfo
import com.didichuxing.doraemonkit.kit.mc.data.AppInfo
import com.didichuxing.doraemonkit.kit.mc.data.HttpUploadInfo
import com.didichuxing.doraemonkit.kit.mc.data.McResInfo
import com.didichuxing.doraemonkit.util.GsonUtils
import com.didichuxing.doraemonkit.volley.VolleyManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.json.JSONObject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
......@@ -29,14 +29,9 @@ object McHttpManager {
const val RESPONSE_OK = 200
const val host = "http://dokit-test.intra.xiaojukeji.com"
// const val host = "http://172.23.166.48"
val mHttpInfoMap: MutableMap<String, HttpInfo> by lazy {
mutableMapOf<String, HttpInfo>()
}
val mExcludeKey: List<String> by lazy {
mutableListOf<String>()
}
var mExcludeKey: List<String> = mutableListOf()
// /**
......@@ -52,29 +47,28 @@ object McHttpManager {
// }
@Throws(Exception::class)
suspend inline fun <reified T> getMcConfig(): McResInfo<T> = suspendCoroutine {
val jsonObject = JSONObject()
jsonObject.put("pId", DoKitConstant.PRODUCT_ID)
val request = JsonObjectRequest(
"$host/app/multiControl/getConfig",
jsonObject,
{ response ->
it.resume(convert2McResInfo(response))
}, { error ->
it.resumeWithException(error)
})
VolleyManager.add(request)
}
suspend inline fun <reified T> getMcConfig(): McResInfo<T> =
suspendCoroutine {
val jsonObject = JSONObject()
jsonObject.put("pId", DoKitConstant.PRODUCT_ID)
val request = JsonObjectRequest(
"$host/app/multiControl/getConfig",
jsonObject,
{ response ->
it.resume(convert2McResInfoWithObj(response))
}, { error ->
it.resumeWithException(error)
})
VolleyManager.add(request)
}
@Throws(Exception::class)
suspend inline fun <reified T> mockStart(): McResInfo<T> = suspendCoroutine {
val request = JsonObjectRequest(
"$host/app/multiControl/startRecord",
JSONObject(GsonUtils.toJson(AppInfo())),
{ response ->
it.resume(convert2McResInfo<T>(response))
it.resume(convert2McResInfoWithObj(response))
}, { error ->
it.resumeWithException(error)
})
......@@ -82,28 +76,26 @@ object McHttpManager {
}
@Throws(Exception::class)
suspend inline fun <reified T> uploadHttpInfo(httpInfo: HttpInfo): McResInfo<T> =
suspend inline fun <reified T> uploadHttpInfo(httpInfo: HttpUploadInfo): McResInfo<T> =
suspendCoroutine {
val request = JsonObjectRequest(
"$host/app/multiControl/uploadApiInfo",
JSONObject(GsonUtils.toJson(httpInfo)),
{ response ->
it.resume(convert2McResInfo(response))
it.resume(convert2McResInfoWithObj(response))
}, { error ->
it.resumeWithException(error)
})
VolleyManager.add(request)
}
@Throws(Exception::class)
suspend inline fun <reified T> mockStop(caseInfo: McCaseInfoDialogProvider.CaseInfo): McResInfo<T> =
suspendCoroutine {
val request = JsonObjectRequest(
"$host/app/multiControl/endRecord",
JSONObject(GsonUtils.toJson(caseInfo)),
{ response ->
it.resume(convert2McResInfo(response))
it.resume(convert2McResInfoWithObj(response))
}, { error ->
it.resumeWithException(error)
})
......@@ -111,13 +103,12 @@ object McHttpManager {
}
@Throws(Exception::class)
suspend inline fun <reified T> caseList(): McResInfo<T> = suspendCoroutine {
suspend inline fun <reified T> caseList(): McResInfo<List<T>> = suspendCoroutine {
val request = StringRequest(
Request.Method.GET,
"$host/app/multiControl/caseList?pId=${DoKitConstant.PRODUCT_ID}",
{ response ->
it.resume(convert2McResInfo(JSONObject(response)))
it.resume(convert2McResInfoWithList(JSONObject(response)))
}, { error ->
it.resumeWithException(error)
})
......@@ -125,35 +116,57 @@ object McHttpManager {
}
@Throws(Exception::class)
suspend inline fun <reified T> httpMatch(requestKey: String): McResInfo<T> = suspendCoroutine {
val jsonObject = JSONObject()
jsonObject.put("key", requestKey)
jsonObject.put("caseId", "caseId")
val request = JsonObjectRequest(
"$host/app/multiControl/getCaseApiInfo",
jsonObject,
{ response ->
it.resume(convert2McResInfo(response))
}, { error ->
it.resumeWithException(error)
})
VolleyManager.add(request)
suspend inline fun <reified T> httpMatch(requestKey: String): McResInfo<T> =
suspendCoroutine {
val request = StringRequest(
"$host/app/multiControl/getCaseApiInfo?key=${requestKey}&pId=${DoKitConstant.PRODUCT_ID}&caseId=${McConstant.MC_CASE_ID}",
{ response ->
it.resume(convert2McResInfoWithObj(JSONObject(response)))
}, { error ->
it.resumeWithException(error)
})
VolleyManager.add(request)
}
inline fun <reified T> convert2McResInfoWithObj(json: JSONObject): McResInfo<T> {
return try {
val mcInfo = McResInfo<T>(
json.optInt("code", 0),
json.optString("msg", "has no msg value")
)
val dataJson = json.optJSONObject("data")
val type = GsonUtils.getType(T::class.java)
mcInfo.data = GsonUtils.fromJson(dataJson.toString(), type)
mcInfo
} catch (e: Exception) {
McResInfo(
0,
"Gson format error",
null
)
}
}
inline fun <reified T> convert2McResInfo(json: JSONObject): McResInfo<T> {
val mcInfo = McResInfo<T>(
json.getInt("code"),
json.getString("msg")
)
val dataInfo: T? = try {
val dataJson = json.getJSONObject("data").toString()
GsonUtils.fromJson(dataJson, T::class.java)
inline fun <reified T> convert2McResInfoWithList(json: JSONObject): McResInfo<List<T>> {
return try {
val mcInfo = McResInfo<List<T>>(
json.optInt("code", 0),
json.optString("msg", "has no msg value")
)
val dataJson = json.optJSONArray("data")
val type = GsonUtils.getListType(T::class.java)
mcInfo.data = GsonUtils.fromJson(dataJson.toString(), type)
mcInfo
} catch (e: Exception) {
null
McResInfo(
0,
"Gson format error",
null
)
}
mcInfo.data = dataInfo
return mcInfo
}
}
\ No newline at end of file
......@@ -2,12 +2,15 @@ package com.didichuxing.doraemonkit.kit.mc.all.ui
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.didichuxing.doraemonkit.kit.core.BaseFragment
import com.didichuxing.doraemonkit.kit.mc.ability.McHttpManager
import com.didichuxing.doraemonkit.kit.mc.all.McConstant
import com.didichuxing.doraemonkit.mc.R
import com.didichuxing.doraemonkit.util.SPUtils
import com.didichuxing.doraemonkit.util.ToastUtils
import com.didichuxing.doraemonkit.widget.recyclerview.DividerItemDecoration
import kotlinx.coroutines.launch
......@@ -23,6 +26,7 @@ import kotlinx.coroutines.launch
*/
class DoKitMcDatasFragment : BaseFragment() {
lateinit var mRv: RecyclerView
lateinit var mEmpty: TextView
lateinit var mAdapter: McCaseListAdapter
override fun onRequestLayout(): Int {
......@@ -33,6 +37,7 @@ class DoKitMcDatasFragment : BaseFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mRv = findViewById(R.id.rv)
mEmpty = findViewById(R.id.tv_empty)
mRv.layoutManager = LinearLayoutManager(requireActivity())
val decoration = DividerItemDecoration(DividerItemDecoration.VERTICAL)
decoration.setDrawable(resources.getDrawable(R.drawable.dk_divider))
......@@ -46,14 +51,42 @@ class DoKitMcDatasFragment : BaseFragment() {
item.isChecked = true
adapter.notifyDataSetChanged()
ToastUtils.showShort("用例${item.caseName}已被选中")
saveCaseId(item.caseId)
}
mRv.adapter = mAdapter
lifecycleScope.launch {
val data = McHttpManager.caseList<MutableList<McCaseInfo>>().data
mAdapter.setList(data)
val data = McHttpManager.caseList<McCaseInfo>().data
data?.let {
if (it.isEmpty()) {
mEmpty.visibility = View.VISIBLE
} else {
val caseId = loadCaseId()
it.forEach { info ->
info.isChecked = caseId == info.caseId
}
mAdapter.setList(it)
}
}
}
}
private fun saveCaseId(caseId: String) {
McConstant.MC_CASE_ID = caseId
SPUtils.getInstance().put("mc_case_id", caseId)
}
private fun loadCaseId(): String {
return if (McConstant.MC_CASE_ID.isEmpty()) {
val caseId = SPUtils.getInstance().getString("mc_case_id", "")
McConstant.MC_CASE_ID = caseId
McConstant.MC_CASE_ID
} else {
McConstant.MC_CASE_ID
}
}
}
\ No newline at end of file
......@@ -23,8 +23,9 @@ import com.didichuxing.doraemonkit.kit.mc.ability.McHttpManager
import com.didichuxing.doraemonkit.kit.mc.ability.McHttpManager.RESPONSE_OK
import com.didichuxing.doraemonkit.kit.mc.all.DoKitWindowManager
import com.didichuxing.doraemonkit.kit.mc.all.McConstant
import com.didichuxing.doraemonkit.kit.mc.all.ui.data.McCaseInfo
import com.didichuxing.doraemonkit.kit.mc.data.McCaseInfo
import com.didichuxing.doraemonkit.kit.mc.client.DoKitWsClient
import com.didichuxing.doraemonkit.kit.mc.data.McConfigInfo
import com.didichuxing.doraemonkit.kit.mc.server.HostInfo
import com.didichuxing.doraemonkit.kit.mc.server.RecordingDokitView
import com.didichuxing.doraemonkit.mc.R
......@@ -69,9 +70,23 @@ class DoKitMcMainFragment : BaseFragment() {
ToastUtils.showShort("当前处于数据录制状态,请先执行上传操作")
return@setOnClickListener
}
if (activity is DoKitMcActivity) {
(activity as DoKitMcActivity).changeFragment(WSMode.HOST)
if (McConstant.MC_CASE_ID.isEmpty()) {
lifecycleScope.launch(exceptionHandler) {
privacyInterceptDialog(
"操作提醒",
"当前未选中任何的数据用例,请确认要否要以数据不同步模式运行?"
).isTrueWithCor {
if (activity is DoKitMcActivity) {
(activity as DoKitMcActivity).changeFragment(WSMode.HOST)
}
}
}
} else {
if (activity is DoKitMcActivity) {
(activity as DoKitMcActivity).changeFragment(WSMode.HOST)
}
}
}
val client = findViewById<Button>(R.id.tv_client)
client.setOnClickListener {
......@@ -81,16 +96,19 @@ class DoKitMcMainFragment : BaseFragment() {
return@setOnClickListener
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (activity?.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
val permissions = arrayOf(Manifest.permission.CAMERA)
requestPermissions(permissions, REQUEST_CODE_CAMERA)
} else {
startScan()
if (McConstant.MC_CASE_ID.isEmpty()) {
lifecycleScope.launch(exceptionHandler) {
privacyInterceptDialog(
"操作提醒",
"当前未选中任何的数据用例,请确认要否要以数据不同步模式运行?"
).isTrueWithCor {
performScan()
}
}
} else {
startScan()
performScan()
}
}
val record = findViewById<Button>(R.id.tv_record)
record.setOnClickListener {
......@@ -106,10 +124,13 @@ class DoKitMcMainFragment : BaseFragment() {
//请求一个CaseId
lifecycleScope.launch(exceptionHandler) {
interceptDialogResult().isTrueWithCor(isFalse = {
ToastUtils.showShort("取消用例采集")
}) {
privacyInterceptDialog(
"隐私提醒",
"用例采集会实时录制并上传接口数据到dokit.cn平台,请确认是否要开启?"
).isTrueWithCor(
isFalse = {
ToastUtils.showShort("取消用例采集")
}) {
try {
val resInfo = McHttpManager.mockStart<McCaseInfo>()
if (resInfo.code == RESPONSE_OK) {
......@@ -136,9 +157,22 @@ class DoKitMcMainFragment : BaseFragment() {
ToastUtils.showShort("DoKit初始化时未传入产品id")
return@setOnClickListener
}
if (McConstant.MC_CASE_ID.isEmpty()) {
ToastUtils.showShort("请先开始执行用例采集")
return@setOnClickListener
}
lifecycleScope.launch(exceptionHandler) {
val result = McHttpManager.mockStop<Any>(mcCaseInfoDialog())
LogHelper.i(TAG, "result===>$result")
if (result.code == RESPONSE_OK) {
DoKitConstant.WS_MODE = WSMode.UNKNOW
SimpleDokitStarter.removeFloating(RecordingDokitView::class.java)
ToastUtils.showShort("用例上传成功")
} else {
LogHelper.e(TAG, "error msg===>${result.msg}")
}
}
}
......@@ -153,11 +187,13 @@ class DoKitMcMainFragment : BaseFragment() {
}
//加载exclude key
if (DoKitConstant.PRODUCT_ID.isNotEmpty()) {
if (DoKitConstant.PRODUCT_ID.isNotBlank()) {
lifecycleScope.launch(exceptionHandler) {
val config = McHttpManager.getMcConfig<Any>()
val config = McHttpManager.getMcConfig<McConfigInfo>()
if (config.code == RESPONSE_OK) {
//LogHelper.i(TAG, "config===>$config")
config.data?.multiControl?.exclude?.let {
McHttpManager.mExcludeKey = it
}
} else {
ToastUtils.showShort(config.msg)
}
......@@ -168,6 +204,23 @@ class DoKitMcMainFragment : BaseFragment() {
}
/**
* 执行扫描
*/
private fun performScan() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (activity?.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
val permissions = arrayOf(Manifest.permission.CAMERA)
requestPermissions(permissions, REQUEST_CODE_CAMERA)
} else {
startScan()
}
} else {
startScan()
}
}
/**
* 开始扫描
*/
......@@ -258,31 +311,32 @@ class DoKitMcMainFragment : BaseFragment() {
/**
* 处理dialog返回值
*/
private suspend fun interceptDialogResult() = suspendCoroutine<Boolean> {
AlertDialog.Builder(requireActivity())
.setTitle("隐私提醒")
.setMessage("开启用例采集会实时录制并上传接口数据到dokit.cn平台!!!")
.setPositiveButton("开启") { dialog, _ ->
dialog.dismiss()
it.resume(true)
}
.setNegativeButton("取消") { dialog, _ ->
dialog.dismiss()
it.resume(false)
}
.show()
private suspend fun privacyInterceptDialog(title: String, content: String): Boolean =
suspendCoroutine {
AlertDialog.Builder(requireActivity())
.setTitle(title)
.setMessage(content)
.setPositiveButton("开启") { dialog, _ ->
dialog.dismiss()
it.resume(true)
}
.setNegativeButton("取消") { dialog, _ ->
dialog.dismiss()
it.resume(false)
}
.show()
}
}
/**
* 确认用例信息
*/
private suspend fun mcCaseInfoDialog() = suspendCoroutine<McCaseInfoDialogProvider.CaseInfo> {
private suspend fun mcCaseInfoDialog(): McCaseInfoDialogProvider.CaseInfo = suspendCoroutine {
showDialog(McCaseInfoDialogProvider(null, object : DialogListener {
override fun onPositive(dialogProvider: DialogProvider<*>): Boolean {
val provider = dialogProvider as McCaseInfoDialogProvider
val (caseName, personName) = provider.getCaseInfo()
val (_, _, caseName, personName) = provider.getCaseInfo()
if (caseName.isBlank()) {
ToastUtils.showShort("用例名称不能为空")
......
......@@ -20,7 +20,7 @@ class McCaseListAdapter(caseList: MutableList<McCaseInfo>) :
override fun convert(holder: BaseViewHolder, item: McCaseInfo) {
holder.getView<TextView>(R.id.tv_name).text = "用例名:${item.caseName}"
holder.getView<TextView>(R.id.tv_person).text = "采集人:${item.person}"
holder.getView<TextView>(R.id.tv_person).text = "采集人:${item.personName}"
holder.getView<TextView>(R.id.tv_time).text = "采集时间:${item.time}"
holder.getView<RadioButton>(R.id.rb).isChecked = item.isChecked
}
......@@ -29,7 +29,8 @@ class McCaseListAdapter(caseList: MutableList<McCaseInfo>) :
data class McCaseInfo(
val caseName: String,
val person: String,
val personName: String,
val time: String,
var isChecked: Boolean
var isChecked: Boolean,
val caseId: String
)
\ No newline at end of file
package com.didichuxing.doraemonkit.kit.mc.ability
package com.didichuxing.doraemonkit.kit.mc.data
import com.didichuxing.doraemonkit.BuildConfig
import com.didichuxing.doraemonkit.constant.DoKitConstant
......
package com.didichuxing.doraemonkit.kit.mc.ability
import android.app.Person
package com.didichuxing.doraemonkit.kit.mc.data
/**
* ================================================
* 作 者:jint(金台)
* 版 本:1.0
* 创建日期:2021/6/22-20:02
* 创建日期:2021/6/21-17:04
* 描 述:
* 修订历史:
* ================================================
*/
data class McUseCaseInfo(
val casePerson: String = "DoKit",
val caseName: String = "DoKit Default Case",
val appInfo: AppInfo = AppInfo(),
val httpInfos: MutableList<HttpInfo> = mutableListOf<HttpInfo>()
data class HttpMatchedInfo(
val key: String,
val responseBody: String
)
package com.didichuxing.doraemonkit.kit.mc.ability
package com.didichuxing.doraemonkit.kit.mc.data
/**
* ================================================
......@@ -9,7 +9,7 @@ package com.didichuxing.doraemonkit.kit.mc.ability
* 修订历史:
* ================================================
*/
data class HttpInfo(
data class HttpUploadInfo(
val pId: String,
val caseId: String,
val key: String,
......@@ -19,5 +19,5 @@ data class HttpInfo(
val contentType: String?,
val query: Map<String, String>?,
val requestBody: Map<String, String>?,
val responseBody4base64: String
val responseBody: String
)
package com.didichuxing.doraemonkit.kit.mc.all.ui.data
package com.didichuxing.doraemonkit.kit.mc.data
import com.google.gson.annotations.Expose
......
package com.didichuxing.doraemonkit.kit.mc.data
/**
* ================================================
* 作 者:jint(金台)
* 版 本:1.0
* 创建日期:2021/7/6-17:12
* 描 述:
* 修订历史:
* ================================================
*/
data class McConfigInfo(val multiControl: MultiControl? = null)
data class MultiControl(val exclude: List<String>? = null)
package com.didichuxing.doraemonkit.kit.mc.all.ui.data
package com.didichuxing.doraemonkit.kit.mc.data
/**
* ================================================
......@@ -9,4 +9,8 @@ package com.didichuxing.doraemonkit.kit.mc.all.ui.data
* 修订历史:
* ================================================
*/
data class McResInfo<T>(val code: Int = 0, val msg: String = "", var data: T? = null)
data class McResInfo<T>(
val code: Int = 0,
val msg: String = "",
var data: T? = null
)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dk_color_FFFFFF"
android:orientation="vertical">
android:background="@color/dk_color_FFFFFF">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
\ No newline at end of file
<TextView
android:id="@+id/tv_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="暂无用例数据"
android:textColor="@color/dk_color_333333"
android:textSize="20sp"
android:visibility="gone" />
</FrameLayout>
\ No newline at end of file
package com.didichuxing.doraemonkit
import com.didichuxing.doraemonkit.kit.mc.all.ui.data.McCaseInfo
import com.didichuxing.doraemonkit.kit.mc.all.ui.data.McResInfo
import com.didichuxing.doraemonkit.kit.mc.data.McCaseInfo
import com.didichuxing.doraemonkit.kit.mc.data.McResInfo
import com.google.gson.Gson
import org.json.JSONObject
import org.junit.Test
......
......@@ -15,6 +15,11 @@ import org.gradle.api.Project
* ================================================
*/
object DoKitExtUtil {
/**
* 是否包含dokitx-rpc模块
*/
var HAS_DOKIT_RPC_MODULE = false
//private var mApplicationId: String = ""
/**
......
......@@ -255,9 +255,8 @@ class CommTransformer : AbsClassTransformer() {
}
}
//didi platform
if (className == "didihttp.DidiHttpClient" && DoKitExtUtil.commExt.didinetSwitch) {
//didi platform 判断是否引入了dokit-rpc模块
if (className == "didihttp.DidiHttpClient" && DoKitExtUtil.commExt.didinetSwitch && DoKitExtUtil.HAS_DOKIT_RPC_MODULE) {
klass.methods?.find {
it.name == "<init>" && it.desc != "()V"
}.let {
......@@ -273,7 +272,10 @@ class CommTransformer : AbsClassTransformer() {
&& fieldInsnNode.desc == "Ljava/util/List;"
}
?.forEach { fieldInsnNode ->
it.instructions.insert(fieldInsnNode, createDidiHttpClientInsnList())
it.instructions.insert(
fieldInsnNode,
createDidiHttpClientInsnList()
)
}
}
}
......
......@@ -56,12 +56,20 @@ class DoKitPluginConfigProcessor(val project: Project) : VariantProcessor {
variants[0],
artifactResult.file.length()
)
if (thirdLibInfo.variant.contains("dokitx-rpc")) {
DoKitExtUtil.HAS_DOKIT_RPC_MODULE = true
}
// "thirdLibInfo.variant===>${thirdLibInfo.variant}".println()
DoKitExtUtil.THIRD_LIB_INFOS.add(thirdLibInfo)
} else if (variants.size == 4) {
thirdLibInfo = ThirdLibInfo(
"porject ${variants[1]}",
artifactResult.file.length()
)
if (thirdLibInfo.variant.contains("doraemonkit-rpc")) {
DoKitExtUtil.HAS_DOKIT_RPC_MODULE = true
}
// "thirdLibInfo.variant===>${thirdLibInfo.variant}".println()
DoKitExtUtil.THIRD_LIB_INFOS.add(thirdLibInfo)
}
......
......@@ -9,6 +9,7 @@ import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.DokitExtInterc
import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.DokitLargePicInterceptor;
import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.DokitMockInterceptor;
import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.DokitWeakNetworkInterceptor;
import com.didichuxing.doraemonkit.util.LogHelper;
import com.didichuxing.doraemonkit.util.ReflectUtils;
import java.util.ArrayList;
......@@ -51,28 +52,42 @@ public class OkHttpHook {
List<Interceptor> interceptors = new ArrayList<>(client.interceptors());
List<Interceptor> networkInterceptors = new ArrayList<>(client.networkInterceptors());
try {
DokitAbility.DokitModuleProcessor processor = DoKitConstant.INSTANCE.getModuleProcessor(DoKitModule.MODULE_MC);
if (processor != null) {
Object interceptor = processor.values().get("okhttp_interceptor");
if (interceptor instanceof AbsDoKitInterceptor) {
interceptors.add((AbsDoKitInterceptor) interceptor);
noDuplicateAdd(interceptors, (AbsDoKitInterceptor) interceptor);
}
}
} catch (Exception e) {
e.printStackTrace();
}
interceptors.add(new DokitMockInterceptor());
interceptors.add(new DokitLargePicInterceptor());
interceptors.add(new DokitCapInterceptor());
interceptors.add(new DokitExtInterceptor());
networkInterceptors.add(new DokitWeakNetworkInterceptor());
noDuplicateAdd(interceptors, new DokitMockInterceptor());
noDuplicateAdd(interceptors, new DokitLargePicInterceptor());
noDuplicateAdd(interceptors, new DokitCapInterceptor());
noDuplicateAdd(interceptors, new DokitExtInterceptor());
noDuplicateAdd(networkInterceptors, new DokitWeakNetworkInterceptor());
//需要用反射重新赋值 因为源码中创建了一个不可变的list
ReflectUtils.reflect(client).field("interceptors", interceptors);
ReflectUtils.reflect(client).field("networkInterceptors", networkInterceptors);
}
//list判断是否重复添加
private static void noDuplicateAdd(List<Interceptor> interceptors, AbsDoKitInterceptor interceptor) {
boolean hasInterceptor = false;
for (Interceptor i : interceptors) {
if (i instanceof AbsDoKitInterceptor) {
if (((AbsDoKitInterceptor) i).getTAG().equals(interceptor.getTAG())) {
hasInterceptor = true;
break;
}
}
}
if (!hasInterceptor) {
interceptors.add(interceptor);
}
}
}
......@@ -6,6 +6,7 @@ import android.os.Bundle
import com.didichuxing.doraemonkit.DoKit
import com.didichuxing.doraemonkit.constant.BundleKey
import com.didichuxing.doraemonkit.constant.FragmentIndex
import kotlin.reflect.KClass
/**
* 悬浮窗和全屏启动器
......@@ -28,6 +29,13 @@ object SimpleDokitStarter {
DokitViewManager.getInstance().attach(doKitIntent)
}
@JvmStatic
fun removeFloating(
targetClass: Class<out AbsDokitView?>,
) {
DokitViewManager.getInstance().detach(targetClass)
}
/**
* @JvmStatic:允许使用java的静态方法的方式调用
......
......@@ -4,10 +4,11 @@ include ':doraemonkit-ft'
include ':doraemonkit'
include ':doraemonkit-mc'
include ':doraemonkit-plugin'
//include ':doraemonkit-no-op'
include ':doraemonkit-okhttp-v3'
include ':doraemonkit-okhttp-v4'
include ':doraemonkit-okhttp-api'
include ':doraemonkit-weex'
//include ':doraemonkit-no-op'
//include ':doraemonkit-rpc'
//include ':doraemonkit-leakcanary'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册