Git Product home page Git Product logo

yangchong211 / ycandroidtool Goto Github PK

View Code? Open in Web Editor NEW
752.0 11.0 169.0 12.65 MB

用于项目测试,崩溃重启操作,崩溃记录日志【可以查看,分享】和重启【多种重启app方式】;网路拦截查看的工具小助手,拦截请求和响应数据,统计接口请求次数,流量消耗,以及统计网络链接/dns解析/request请求/respond响应等时间。提高开发效率……

Java 99.99% AIDL 0.01%

ycandroidtool's Introduction

目录介绍

  • 01.该库具有的功能
  • 02.崩溃收集模块
  • 03.网络分析模块
  • 04.ping库模块
  • 05.磁盘file模块
  • 06.卡顿监测模块
  • 07.如何使用该库
  • 08.其他待完善项

01.该库具有的功能

  • 最大特点
    • 入侵性低,你不用改动愿项目代码,几行代码设置即可使用这几个模块功能,已经用于多个实际项目中。如果觉得可以,麻烦star一下……
  • 功能齐全
    • 包括平常看到的卡顿分析,收集,监控;Anr模拟,监控和日志收集;崩溃拦截处理和日志界面展示;网络接口请求数据的收集和ping。以及超全的系列文档

1.1 崩溃收集模块

  • 崩溃模块
    • 崩溃重启操作,崩溃记录日志操作,崩溃日志列表支持查询,删除,查看详情,分享,保存文本,以及截图等操作。
  • 崩溃分析流程
    • 从崩溃流程分析,到拦截App崩溃,然后收集崩溃相关信息,记录到file文件,以及到UI界面展示。一体化来学习崩溃的系统化处理。

1.2 网络分析模块

  • 网络分析库模块
    • 网络流程分析,记录每个网络请求->响应数据,方便查看很全面的请求头信息,响应头信息,以及body实体。
  • ping库模块
    • 通过ping检测网络问题,帮助诊断,这个在Android中检查域名的诊断信息……
  • 查看网络时间和流量
    • 网络连接,dns解析,TLS连接,请求响应等时间差……都可以记录下来通过界面展示

1.3 卡顿监测模块

  • 支持fps查看帧率
    • 一键便可以开启查看页面的帧率。
  • 卡顿监控方案
    • LooperPrinter实现卡顿监控,卡顿之后的数据收集,
    • WatchDog卡顿监控,作为一种学习案例,理解它监控卡顿的原理。

1.4 ANR监测模块

02.崩溃收集模块

2.1 异常崩溃介绍

  • 低入侵性接入该lib,不会影响你的其他业务。
    • 暴露崩溃重启,以及支持开发者自己捕获crash数据的接口!能够收集崩溃中的日志写入文件,记录包括设备信息,进程信息,崩溃信息(Java崩溃、Native崩溃 or ANR),以及崩溃时内存信息到file文件中。支持用户获取崩溃列表,以及跳转崩溃日志详情页面,并且可以将崩溃日志分享,截长图,复制等操作。可以方便测试和产品给开发提出那种偶发性bug的定位日志,免得对于偶发行崩溃,开发总是不承认……开发总是不承认……

2.2 截图如下所示

image image image image

2.3崩溃后日志记录

image

2.4 崩溃流程图

image

03.网络分析模块

3.1 网络分析库模块

  • 如何拿来用
    • 既然Android中使用到facebook的stetho库,可以拦截手机请求请求,然后去Chrome浏览器,在浏览器地址栏输入:chrome://inspect 。即可查看请求信息。
    • 那么能不能把这个拿到的请求信息,放到集合中,然后在Android的页面中展示呢?这样方便开发和测试查看网络请求信息,以及请求流程中的消耗时间(比如dns解析时间,请求时间,响应时间,共耗时等等)
  • OkHttp如何进行各个请求环节的耗时统计呢?
    • OkHttp 版本提供了EventListener接口,可以让调用者接收一系列网络请求过程中的事件,例如DNS解析、TSL/SSL连接、Response接收等。
    • 通过继承此接口,调用者可以监视整个应用中网络请求次数、流量大小、耗时(比如dns解析时间,请求时间,响应时间等等)情况。因此统计耗时,需要致敬EventListener实现,照搬代码即可。
  • 如何消耗记录时间
    • 在OkHttp库中有一个EventListener类。该类是网络事件的侦听器。扩展这个类以监视应用程序的HTTP调用的数量、大小和持续时间。
    • 所有启动/连接/获取事件最终将接收到匹配的结束/释放事件,要么成功(非空参数),要么失败(非空可抛出)。
    • 比如,可以在开始链接记录时间;dns开始,结束等方法解析记录时间,可以计算dns的解析时间。

3.2 网络拦截库功能

  • 网络请求拦截
    • 记录每个页面网络请求的数据,保存在map中,方便查看网络请求的请求头,响应头,响应body
    • 针对获取的网络数据,记录网络状态,请求耗时,请求方式,完善了网络日志包括的绝大部分字段信息展示
  • 流量统计
    • 目前只是针对get,post网络请求以及上传流量统计,并且针对get和post比例展示,以及抓包数量统计
    • 后期完善比如glide加载图片消耗的流量统计
  • 网络消耗时间
    • 网络请求到完成耗时,dns消耗时间,连接消耗时间,TLS连接开始结束消耗时间,request请求消耗时间,response响应消耗时间等等
  • 设备信息
    • 获取手机设备信息,包括硬件厂商,版本,root,包名等信息
    • 获取本机wifi信息,主要是wifi的名称,mac地址,ip地址,dns信息,子网掩码等
    • 获取服务端信息,根据网络请求host,获取服务端ip,mac,是ipv4还是ipv6等,这个还在完善中
  • ping网络诊断
    • 致敬网易ping方案,应用于Android项目中,获取Android项目域名,拿到ping信息
  • 全局悬浮按钮
    • 为了方便查看每个activity页面的网络请求数据,因此在每个activity页面显示全局悬浮按钮,点击即可跳入查看数据页面
    • 这个一行代码设置即可,无任何耦合作用,低入侵

3.3 网络请求接口信息

3.4 案例截图如下

image image image image image

04.ping库模块

4.1 ping在Android的应用

  • 为了检查网络,在android上也可以通过ping来查看是否网络通。
  • 实现方案有哪些
    • 通过后台线程执行ping命令的方式模拟traceroute的过程,缺点就是模拟过程较慢,timeout的出现比较频繁
    • 通过编译开源网络检测库iputilsC代码的方式对traceroute进行了套接字发送ICMP报文模拟,可以明显提高检测速度

4.2 ping使用截图

image

05.磁盘file模块

5.1 项目背景说明

  • app展示在数据量多且刷新频繁的情况下,为提升用户体验,通常会对上次已有数据做内存缓存或磁盘缓存,以达到快速展示数据的目的。缓存的数据变化是否正确、缓存是否起到对应作用是QA需要重点测试的对象。
  • android缓存路径查看方法有哪些呢?将手机打开开发者模式并连接电脑,在pc控制台输入cd /data/data/目录,使用adb主要是方便测试(删除,查看,导出都比较麻烦)。
  • 如何简单快速,傻瓜式的查看缓存文件,操作缓存文件,那么该项目小工具就非常有必要呢!采用可视化界面读取缓存数据,方便操作,直观也简单。

5.2 沙盒作用

  • 可以通过该工具查看缓存文件
    • 快速查看data/data/包名目录下的缓存文件。
    • 快速查看/sdcard/Android/data/包名下存储文件。
  • 对缓存文件处理
    • 支持查看file文件列表数据,打开缓存文件查看数据详情。还可以删除缓存对应的文件或者文件夹,并且友好支持分享到外部。
    • 能够查看缓存文件修改的信息,修改的时间,缓存文件的大小,获取文件的路径等等。都是在可视化界面上处理。

5.3 设计目标

  • 可视化界面展示 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
  • 多种处理文件操作
    • 针对file文件夹,或者file文件,长按可以出现弹窗,让测试选择是否删除文件。
    • 点击file文件夹,则拿到对应的文件列表,然后展示。点击file直到是具体文件(文本,图片,db,json等非file文件夹)跳转详情。
  • 一键接入该工具
    • FileExplorerActivity.startActivity(MainActivity.this);

07.如何使用该库

7.1 崩溃库

  • 如何引入该库
    //磁盘文件查看工具
    implementation 'com.github.yangchong211.YCAndroidTool:MonitorFileLib:1.2.8'
    //卡顿工具
    implementation 'com.github.yangchong211.YCAndroidTool:MonitorCatonLib:1.2.8'
    //网络工具
    implementation 'com.github.yangchong211.YCAndroidTool:MonitorNetLib:1.2.8'
    //崩溃工具
    implementation 'com.github.yangchong211.YCAndroidTool:MonitorCrashLib:1.2.8'
    //anr工具
    implementation 'com.github.yangchong211.YCAndroidTool:MonitorAnrLib:1.2.8'
  • 初始化代码如下所示。建议在Application中初始化……
    CrashHandler.getInstance().init(this, new CrashListener() {
        /**
         * 重启app
         */
        @Override
        public void againStartApp() {
            CrashToolUtils.reStartApp1(App.this,1000);
            //CrashToolUtils.reStartApp2(App.this,1000, MainActivity.class);
            //CrashToolUtils.reStartApp3(AppManager.getAppManager().currentActivity());
        }
    
        /**
         * 自定义上传crash,支持开发者上传自己捕获的crash数据
         * @param ex                        ex
         */
        @Override
        public void recordException(Throwable ex) {
            //自定义上传crash,支持开发者上传自己捕获的crash数据
            //StatService.recordException(getApplication(), ex);
        }
    });
  • 关于重启App的操作有三种方式api
    //开启一个新的服务KillSelfService,用来重启本APP【使用handler延迟】
    CrashToolUtils.reStartApp1(App.this,1000);
    //用来重启本APP[使用闹钟,整体重启,临时数据清空(推荐)]
    CrashToolUtils.reStartApp2(App.this,1000, MainActivity.class);
    //检索获取项目中LauncherActivity,然后设置该activity的flag和component启动app【推荐】
    CrashToolUtils.reStartApp3(AppManager.getAppManager().currentActivity());
  • 关于获取崩溃目录api
    //崩溃文件存储路径:/storage/emulated/0/Android/data/你的包名/cache/crashLogs
    //崩溃页面截图存储路径:/storage/emulated/0/Android/data/你的包名/cache/crashPics
    String crashLogPath = ToolFileUtils.getCrashLogPath(this);
    String crashPicPath = ToolFileUtils.getCrashPicPath(this);
  • 关于崩溃日志记录
    • 日志记录路径:/storage/emulated/0/Android/data/你的包名/cache/crashLogs
    • 日志文件命名:V1.0_2020-09-02_09:05:01_java.lang.NullPointerException.txt【版本+日期+异常】
  • 关于跳转错误日志list列表页面
    • 跳转日志列表页面如下所示,这里调用一行代码即可。点击该页面list条目即可进入详情
    CrashToolUtils.startCrashListActivity(this);
  • 那么如何获取所有崩溃日志的list呢。建议放到子线程中处理!!
    List<File> fileList = ToolFileUtils.getCrashFileList(this);
    
    //如果是要自己拿到这些文件,建议根据时间来排个序
    //排序
    Collections.sort(fileList, new Comparator<File>() {
        @Override
        public int compare(File file01, File file02) {
            try {
                //根据修改时间排序
                long lastModified01 = file01.lastModified();
                long lastModified02 = file02.lastModified();
                if (lastModified01 > lastModified02) {
                    return -1;
                } else {
                    return 1;
                }
            } catch (Exception e) {
                return 1;
            }
        }
    });
  • 如何删除单个文件操作
    //返回true表示删除成功
    boolean isDelete = ToolFileUtils.deleteFile(file.getPath());
  • 如何删除所有的文件。建议放到子线程中处理!!
    File fileCrash = new File(ToolFileUtils.getCrashLogPath(CrashListActivity.this));
    ToolFileUtils.deleteAllFiles(fileCrash);
  • 如何获取崩溃文件中的内容
    //获取内容
    String crashContent = ToolFileUtils.readFile2String(filePath);
  • 还有一些关于其他的api,如下。这个主要是方便测试同学或者产品,避免开发不承认那种偶发性崩溃bug……
    //拷贝文件,两个参数分别是源文件,还有目标文件
    boolean copy = ToolFileUtils.copyFile(srcFile, destFile);
    //分享文件。这个是调用原生的分享
    CrashLibUtils.shareFile(CrashDetailsActivity.this, destFile);
    //截图崩溃然后保存到相册。截图---> 创建截图存储文件路径---> 保存图片【图片质量,缩放比还有采样率压缩】
    final Bitmap bitmap = ScreenShotsUtils.measureSize(this,view);
    String crashPicPath = ToolFileUtils.getCrashPicPath(CrashDetailsActivity.this) + "/crash_pic_" + System.currentTimeMillis() + ".jpg";
    boolean saveBitmap = CrashLibUtils.saveBitmap(CrashDetailsActivity.this, bitmap, crashPicPath);
    
  • 异常恢复原理
    • 第一种方式,开启一个新的服务KillSelfService,用来重启本APP。
      CrashToolUtils.reStartApp1(App.this,1000);
    • 第二种方式,使用闹钟延时,然后重启app
      CrashToolUtils.reStartApp2(App.this,1000, MainActivity.class);
    • 第三种方式,检索获取项目中LauncherActivity,然后设置该activity的flag和component启动app
      CrashToolUtils.reStartApp3(AppManager.getAppManager().currentActivity());
    • 关于app启动方式详细介绍

7.2 如何网络拦截

  • 如下所示
    new OkHttpClient.Builder()
        //配置工厂监听器。主要是计算网络过程消耗时间
        .eventListenerFactory(NetworkListener.get())
        //主要是处理拦截请求,响应等信息
        .addNetworkInterceptor(new NetworkInterceptor())
        .build()
  • 如何开启悬浮按钮
    //建议只在debug环境下显示,点击去网络拦截列表页面查看网络请求数据
    NetworkTool.getInstance().setFloat(getApplication());
    
  • 该库目的
    • 做成悬浮全局按钮,点击按钮可以查看该activity页面请求接口,可以查看请求几个接口,以及接口请求到响应消耗流量
    • 方便查看网络请求流程,比如dns解析时间,请求时间,响应时间
    • 方便测试查看请求数据,方便抓包。可以复制request,respond,body等内容。也可以截图

7.3 如何使用ping

  • 直接创建一个ping,需要传递一个网址url
    _netDiagnoService = new NetDiagnoService(getContext(), getContext().getPackageName()
            , versionName, userId, deviceId, host, this);
    _netDiagnoService.execute();
  • 如何取消ping
    if (_netDiagnoService!=null){
        _netDiagnoService.cancel(true);
        _netDiagnoService = null;
    }
  • 或者直接停止ping。停止线程允许,并把对象设置成null
    _netDiagnoService.stopNetDialogsis();
  • 关于监听
    /**
     * 诊断结束,输出全部日志记录
     * @param log                       log日志输出
     */
    @Override
    public void OnNetDiagnoFinished(String log) {
        setText(log);
    }
    
    /**
     * 监控网络诊断过程中的日志输出
     * @param log                       log日志输出
     */
    @Override
    public void OnNetDiagnoUpdated(String log) {
        showInfo += log;
        setText(showInfo);
    }

ycandroidtool's People

Contributors

yangchong211 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ycandroidtool's Issues

natice crash 无法记录

调用一个第三库,出现 “Fatal signal 11 (SIGSEGV), code 1, fault addr 0x23 in tid 7170 (pool-4-thread-1)” native 异常,该库无法捕获记录,bugly 是可以的

使用NetworkTool.getInstance().setFloat(APP.this);点击悬浮窗崩溃报错

22-11-18 16:52:08.624 23367-23367/com.lzw.mvvmdemo.sample D/AndroidRuntime: Shutting down VM
    
    
    --------- beginning of crash
2022-11-18 16:52:08.626 23367-23367/com.lzw.mvvmdemo.sample E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.lzw.mvvmdemo.sample, PID: 23367
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
        at com.yc.netlib.utils.NetDeviceUtils.getAvailMemory(NetDeviceUtils.java:425)
        at com.yc.netlib.ui.NetRequestPhoneFragment.setPhoneInfo(NetRequestPhoneFragment.java:205)
        at com.yc.netlib.ui.NetRequestPhoneFragment.initData(NetRequestPhoneFragment.java:159)
        at com.yc.netlib.ui.NetRequestPhoneFragment.onViewCreated(NetRequestPhoneFragment.java:105)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1971)
        at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311)
        at androidx.fragment.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:249)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
        at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
        at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6753)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:737)
        at android.view.View.measure(View.java:23223)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2812)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1662)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1946)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1550)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7447)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1065)
        at android.view.Choreographer.doCallbacks(Choreographer.java:877)
        at android.view.Choreographer.doFrame(Choreographer.java:808)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1051)
        at android.os.Handler.handleCallback(Handler.java:873)
2022-11-18 16:52:08.626 23367-23367/com.lzw.mvvmdemo.sample E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6806)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

网络拦截库用不了

Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference

在NetDeviceUtils的getAvailMemory方法下

ConcurrentModificationException异常不会走保存的

修改
CrashHandler.java
//收集crash信息
String msg = ex.getLocalizedMessage();
if (msg == null) {
msg = ex.getStackTrace().toString();
// return false;
}

CrashFileUtils.java
if (string.contains(":")) {
splitEx = ex.toString().split(":")[0];
} else {
splitEx = ex.toString();//"java.lang.Exception";
}

崩溃日志记录

大佬,现在网络库又崩溃,我们崩溃日志收集比较多
Caused by: java.util.ConcurrentModificationException
2.at java.util.ArrayList$Itr.next(ArrayList.java:860)
3.at com.yc.toollib.network.ui.NetworkManager.getRecord(NetworkManager.java:31)
4.at com.yc.toollib.network.stetho.DataTranslator.parseAndSaveBody(DataTranslator.java:171)
5.at com.yc.toollib.network.stetho.DataTranslator.saveInterpretResponseStream(DataTranslator.java:129)
6.at com.yc.toollib.network.stetho.NetworkReporterImpl.interpretResponseStream(NetworkReporterImpl.java:73)
7.at com.yc.toollib.network.stetho.NetworkInterceptor.intercept(NetworkInterceptor.java:109)
8.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
9.at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:43)
10.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
11.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
12.at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
13.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
14.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
15.at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
16.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
17.at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
18.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
19.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
20.at com.networkbench.agent.impl.h.d.intercept(SourceFile:84)
21.at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
22.... 10 more

https Total Time 为负数

okhttp :3.12.12
源码依赖,测试请求https请求,消耗时间为负数,测试多次结果一样, 在3.14.X,4.X上没有问题

保存错误日志到文件时为什么没开线程去写呢?

/**
 * 当UncaughtException发生时会转入该函数来处理
 * 该方法来实现对运行时线程进行异常处理
 */
@Override
public void uncaughtException(Thread thread, Throwable ex) {
    Log.e("TAG", "uncaughtException: 。。。。。。。。。" );
    boolean isHandle = handleException(ex);
    initCustomBug(ex);
    if (mDefaultHandler != null && !isHandle) {
        //收集完信息后,交给系统自己处理崩溃
        //uncaughtException (Thread t, Throwable e) 是一个抽象方法
        //当给定的线程因为发生了未捕获的异常而导致终止时将通过该方法将线程对象和异常对象传递进来。
        mDefaultHandler.uncaughtException(thread, ex);
    } else {
        //否则自己处理
        if (mContext instanceof Application){
            ToolLogUtils.w(TAG, "handleException--- ex----重启activity-");
            if (listener!=null){
                listener.againStartApp();
            }
        }
    }
    CrashHelper.getInstance().setSafe(thread,ex);
}

=============================================================
我在这个uncaughtException获取当前线程。得到的当前线程是main线程。 为什么写文件时没有去开线程呢?
我试了去开启线程去写。 偶尔文件会写不成功。程序就直接挂了。 有时又是成功的。
请问作者是否可以解答下我这个疑问呢。 非常非常感谢。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.