From b2b04ff9498e96fd6280001d2a05ed4656f47ffd Mon Sep 17 00:00:00 2001 From: jackjintai Date: Wed, 29 Apr 2020 10:22:32 +0800 Subject: [PATCH] =?UTF-8?q?android:=20=E6=96=B0=E5=A2=9E=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Android/app/build.gradle | 2 +- Android/config.gradle | 2 +- .../doraemonkit/plugin/DoKitPlugin.java | 7 +- .../aop/method_stack/MethodStackUtil.java | 16 +- .../doraemonkit/constant/FragmentIndex.java | 5 + .../kit/core/UniversalActivity.java | 5 + .../kit/timecounter/AppStartInfoFragment.java | 146 ++++++++++++++++++ .../timecounter/TimeCounterListAdapter.java | 13 +- .../res/layout/dk_fragment_app_start_info.xml | 31 ++++ .../src/main/res/values/strings.xml | 2 + 10 files changed, 215 insertions(+), 14 deletions(-) create mode 100644 Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/AppStartInfoFragment.java create mode 100644 Android/doraemonkit/src/main/res/layout/dk_fragment_app_start_info.xml diff --git a/Android/app/build.gradle b/Android/app/build.gradle index 9fb15b93..2c1d8cda 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -81,7 +81,7 @@ dokitExt { slowMethod { //0:默认模式 打印函数调用栈 需添加指定入口 默认为application onCreate 和attachBaseContext //1:普通模式 运行时打印某个函数的耗时 全局业务代码函数插入 - strategy 1 + strategy 0 //函数功能开关 methodSwitch true diff --git a/Android/config.gradle b/Android/config.gradle index 85d4efdd..0007faf4 100755 --- a/Android/config.gradle +++ b/Android/config.gradle @@ -51,7 +51,7 @@ ext { //将urlconnection代理到okhttp //"okhttp_urlconnection" : "com.squareup.okhttp3:okhttp-urlconnection:3.12.1", //"okio" : "com.squareup.okio:okio:1.15.0", - "utilcode" : 'com.blankj:utilcodex:1.28.0', + "utilcode" : 'com.blankj:utilcodex:1.28.3', "glide" : "com.github.bumptech.glide:glide:${android["glide_version"]}", "glide_v3" : 'com.github.bumptech.glide:glide:3.8.0', "glide_okhttp3" : "com.github.bumptech.glide:okhttp3-integration:${android["glide_version"]}", diff --git a/Android/doraemonkit-plugin/src/main/groovy/com/didichuxing/doraemonkit/plugin/DoKitPlugin.java b/Android/doraemonkit-plugin/src/main/groovy/com/didichuxing/doraemonkit/plugin/DoKitPlugin.java index 73786f5f..aa4fc5d7 100644 --- a/Android/doraemonkit-plugin/src/main/groovy/com/didichuxing/doraemonkit/plugin/DoKitPlugin.java +++ b/Android/doraemonkit-plugin/src/main/groovy/com/didichuxing/doraemonkit/plugin/DoKitPlugin.java @@ -1,9 +1,7 @@ package com.didichuxing.doraemonkit.plugin; import com.android.build.gradle.AppExtension; -import com.didichuxing.doraemonkit.plugin.extension.CommExt; import com.didichuxing.doraemonkit.plugin.extension.DoKitExt; -import com.didichuxing.doraemonkit.plugin.extension.SlowMethodExt; import com.didichuxing.doraemonkit.plugin.transform.DokitBigImageTransform; import com.didichuxing.doraemonkit.plugin.transform.DokitCommTransform; import com.didichuxing.doraemonkit.plugin.transform.DokitMethodStack0Transform; @@ -16,7 +14,6 @@ import com.didichuxing.doraemonkit.plugin.transform.DokitUrlConnectionTransform; import com.didiglobal.booster.gradle.BaseVariantKt; import com.didiglobal.booster.gradle.VariantScopeKt; -import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -54,6 +51,8 @@ public final class DoKitPlugin implements Plugin { } } + isDebug = true; + //解析注册表文件 appExtension.getApplicationVariants().all(applicationVariant -> { if (applicationVariant.getName().contains("debug")) { @@ -80,7 +79,7 @@ public final class DoKitPlugin implements Plugin { //项目评估之后回调 project.afterEvaluate(partProject -> { try { - if(isDebug){ + if (isDebug) { DoKitExt dokitExtension = partProject.getExtensions().getByType(DoKitExt.class); System.out.println("DokitPluginExt==>" + dokitExtension.toString()); DoKitExtUtil.getInstance().init(dokitExtension, appExtension); diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/aop/method_stack/MethodStackUtil.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/aop/method_stack/MethodStackUtil.java index c79fcd01..51fc8f89 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/aop/method_stack/MethodStackUtil.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/aop/method_stack/MethodStackUtil.java @@ -26,11 +26,11 @@ public class MethodStackUtil { /** * key className&methodName */ - private static ConcurrentHashMap ROOT_METHOD_STACKS = new ConcurrentHashMap<>(); - private static ConcurrentHashMap LEVEL1_METHOD_STACKS = new ConcurrentHashMap<>(); - private static ConcurrentHashMap LEVEL2_METHOD_STACKS = new ConcurrentHashMap<>(); - private static ConcurrentHashMap LEVEL3_METHOD_STACKS = new ConcurrentHashMap<>(); - private static ConcurrentHashMap LEVEL4_METHOD_STACKS = new ConcurrentHashMap<>(); + private ConcurrentHashMap ROOT_METHOD_STACKS = new ConcurrentHashMap<>(); + private ConcurrentHashMap LEVEL1_METHOD_STACKS = new ConcurrentHashMap<>(); + private ConcurrentHashMap LEVEL2_METHOD_STACKS = new ConcurrentHashMap<>(); + private ConcurrentHashMap LEVEL3_METHOD_STACKS = new ConcurrentHashMap<>(); + private ConcurrentHashMap LEVEL4_METHOD_STACKS = new ConcurrentHashMap<>(); /** @@ -125,7 +125,6 @@ public class MethodStackUtil { //打印函数调用栈 if (level == 0) { - if (methodInvokNode != null) { toStack(classObj instanceof Application, methodInvokNode); } @@ -138,8 +137,11 @@ public class MethodStackUtil { TimeCounterManager.get().onAppAttachBaseContextEnd(); } } - } + //移除对象 + ROOT_METHOD_STACKS.remove(className + "&" + methodName); + + } } catch (Exception e) { e.printStackTrace(); } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java index 16a74f61..216b4c60 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java @@ -53,4 +53,9 @@ public interface FragmentIndex { * 健康体检 */ int FRAGMENT_HEALTH = 27; + + /** + * APP启动耗时 + */ + int FRAGMENT_APP_START = 28; } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/core/UniversalActivity.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/core/UniversalActivity.java index 35370dc1..2b80c905 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/core/UniversalActivity.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/core/UniversalActivity.java @@ -26,6 +26,7 @@ import com.didichuxing.doraemonkit.kit.parameter.cpu.CpuMainPageFragment; import com.didichuxing.doraemonkit.kit.parameter.frameInfo.FrameInfoFragment; import com.didichuxing.doraemonkit.kit.parameter.ram.RamMainPageFragment; import com.didichuxing.doraemonkit.kit.sysinfo.SysInfoFragment; +import com.didichuxing.doraemonkit.kit.timecounter.AppStartInfoFragment; import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterFragment; import com.didichuxing.doraemonkit.kit.weaknetwork.WeakNetworkFragment; import com.didichuxing.doraemonkit.kit.webdoor.WebDoorDefaultFragment; @@ -135,6 +136,10 @@ public class UniversalActivity extends BaseActivity { case FragmentIndex.FRAGMENT_HEALTH: fragmentClass = HealthFragment.class; break; + case FragmentIndex.FRAGMENT_APP_START: + fragmentClass = AppStartInfoFragment.class; + break; + default: break; } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/AppStartInfoFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/AppStartInfoFragment.java new file mode 100644 index 00000000..3759adda --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/AppStartInfoFragment.java @@ -0,0 +1,146 @@ +package com.didichuxing.doraemonkit.kit.timecounter; + +import android.os.Bundle; +import android.text.Html; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.blankj.utilcode.util.AppUtils; +import com.blankj.utilcode.util.FileIOUtils; +import com.blankj.utilcode.util.FileUtils; +import com.blankj.utilcode.util.PathUtils; +import com.blankj.utilcode.util.ThreadUtils; +import com.blankj.utilcode.util.TimeUtils; +import com.blankj.utilcode.util.ToastUtils; +import com.didichuxing.doraemonkit.DoraemonKit; +import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.aop.method_stack.MethodStackUtil; +import com.didichuxing.doraemonkit.kit.core.BaseFragment; +import com.didichuxing.doraemonkit.kit.core.SettingItem; +import com.didichuxing.doraemonkit.kit.core.SettingItemAdapter; +import com.didichuxing.doraemonkit.kit.loginfo.LogLine; +import com.didichuxing.doraemonkit.util.FileUtil; +import com.didichuxing.doraemonkit.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.widget.titlebar.TitleBar; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * @desc: Activity跳转耗时检测首页 + */ + +public class AppStartInfoFragment extends BaseFragment { + TextView mInfo; + + @Override + protected int onRequestLayout() { + return R.layout.dk_fragment_app_start_info; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(); + } + + + private void initView() { + TitleBar titleBar = findViewById(R.id.title_bar); + + titleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() { + @Override + public void onLeftClick() { + finish(); + } + + @Override + public void onRightClick() { + export2File(mInfo.getText().toString()); + } + }); + + mInfo = findViewById(R.id.app_start_info); + StringBuilder builder = new StringBuilder(); + if (TextUtils.isEmpty(MethodStackUtil.STR_APP_ATTACH_BASECONTEXT)) { + builder.append("只有配置slowMethod的strategy=0模式下才能统计到启动函数调用栈"); + } else { + builder.append(MethodStackUtil.STR_APP_ATTACH_BASECONTEXT); + builder.append("\n"); + builder.append(MethodStackUtil.STR_APP_ON_CREATE); + } + + mInfo.setText(builder.toString()); + + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + /** + * 将启动信息保存到文件并分享 + */ + private void export2File(final String info) { + if (TextUtils.isEmpty(info)) { + ToastUtils.showShort("启动信息为空"); + return; + } + ToastUtils.showShort("启动信息保存中,请稍后..."); + final String logPath = PathUtils.getInternalAppFilesPath() + File.separator + AppUtils.getAppName() + "_" + "app_launch.log"; + final File logFile = new File(logPath); + + ThreadUtils.executeByCpu(new ThreadUtils.Task() { + @Override + public Boolean doInBackground() throws Throwable { + try { + + FileIOUtils.writeFileFromString(logFile, info, false); + + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + @Override + public void onSuccess(Boolean result) { + if (result) { + ToastUtils.showShort("启动信息文件保存在:" + logPath); + //分享 + FileUtil.systemShare(DoraemonKit.APPLICATION, logFile); + } + } + + @Override + public void onCancel() { + if (logFile.exists()) { + FileUtils.delete(logFile); + } + ToastUtils.showShort("启动信息保存失败"); + } + + @Override + public void onFail(Throwable t) { + if (logFile.exists()) { + FileUtils.delete(logFile); + } + ToastUtils.showShort("启动信息保存失败"); + } + }); + + } + + +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java index f0a43922..f1ae7bda 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java @@ -1,6 +1,7 @@ package com.didichuxing.doraemonkit.kit.timecounter; import android.content.Context; +import android.content.Intent; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -8,6 +9,9 @@ import android.view.ViewGroup; import android.widget.TextView; import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.constant.BundleKey; +import com.didichuxing.doraemonkit.constant.FragmentIndex; +import com.didichuxing.doraemonkit.kit.core.UniversalActivity; import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo; import com.didichuxing.doraemonkit.widget.recyclerview.AbsRecyclerAdapter; import com.didichuxing.doraemonkit.widget.recyclerview.AbsViewBinder; @@ -16,7 +20,6 @@ import static android.text.format.DateUtils.FORMAT_SHOW_TIME; public class TimeCounterListAdapter extends AbsRecyclerAdapter, CounterInfo> { - public TimeCounterListAdapter(Context context) { super(context); } @@ -73,6 +76,13 @@ public class TimeCounterListAdapter extends AbsRecyclerAdapter + + + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/values/strings.xml b/Android/doraemonkit/src/main/res/values/strings.xml index c387e187..1312e725 100644 --- a/Android/doraemonkit/src/main/res/values/strings.xml +++ b/Android/doraemonkit/src/main/res/values/strings.xml @@ -176,6 +176,7 @@ 可见Fragments:%1$s 返回 + 导出 流量监控摘要 流量监控列表 @@ -241,6 +242,7 @@ Activity跳转耗时 查看记录 耗时列表 + 启动详情 提交 取消 -- GitLab