【安卓学习之第三方库】 Tencent Matrix-android使用-ANR

█ 【安卓学习之第三方库】 Tencent Matrix使用-ANR

█ 系列文章目录

小贴士:以下是关于Android学习的常见问题的文章集

[En]

Tip: here is a collection of articles about common questions about Android learning

█ 文章目录

█ 读前说明

  • 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
  • 本文简单列出了相关代码实现流程。
    [En]

    this article simply lists the relevant code implementation process.*

  • 涉及的逻辑和解释仅为简要介绍,主要作为了解过程的说明。
    [En]

    the logic and explanation involved are only a brief introduction, mainly as notes to understand the process.*

  • Android 微信 APM工具 Matrix-android

█ Matrix-android、bugly、leakcanary

  1. Canary

Canary(金丝雀) Bleeding Edge(一种最新的、因而也并非完美的技术),大约周更。这是最早被发布的预览版本,

Stable稳定版/正式版适合追求稳定的普通用户使用。beta测试版适合喜欢较稳定又可尝鲜的朋友下载使用。该版本是新的正式版发布前的公开测试所用,版本上的新功能不会作太多修改,主要为安全上的测试,但可能会存在不稳定情况。dev开发版适合开发人员使用。主要为功能上的测试,可能存在稳定性问题,通常更新速度为一周一次。canary金丝雀版本仅适合开发人员或追求最新版本的用户使用。2010年7月加入,比开发版更新快但更不稳定,相对的也会加入更多测试性的新功能。

  1. Matrix-android

功能收集崩溃、ANR、卡顿和爆内存数据监控范围应用安装包大小,帧率变化,启动耗时,卡顿,慢方法,SQLite 操作优化,文件读写,内存泄漏等等示例
samples/sample-android/app

注意由于 JCenter 服务将于 2022 年 2 月 1 日下线,我们已将 Matrix 新版本(>= 0.8.0) maven repo 发布至 MavenCentral。

Matrix 各模块

基础包matrix-android-lib初始化监听等,含Matrix、Matrix.Builder、Issue、

IDynamicConfig、DefaultPluginListener、MatrixLog-matrix-android-commons目前没用Resource Canarymatrix-resource-canary-android

matrix-resource-canary-common便于在不打断自动化测试的前提下持续输出分析后的检测结果,检测重复 Bitmap 对象Trace Canarymatrix-trace-canary准确监控ANR ,保存系统产生的ANR Trace文件SQLite Lintmatrix-sqlite-lint-android-sdk把控SQLite质量IO Canarymatrix-io-canaryIO 性能、泄漏全面监控Battery Canarymatrix-battery-canary耗电量优化Memory Hook

Pthread Hook

WVPreAllocHookmatrix-hooks内存泄漏

线程泄漏\native 线程栈空间

WebView内存分配APK Checkermatrix-apk-canary-2.0.0.jar追踪和对比每个 APK 版本之间的变化Backtrace Component-快速回溯 native 调用栈的 backtrace 组件

  1. bugly
    异常上报,应用集成SDK后,即可在Web站点查看应用上报的崩溃数据和联网数据。
    缺点:android6.0以后的设备,无法上传 ANR日志
    【安卓学习之第三方库】 Tencent Matrix-android使用-ANR
  2. leakcanary

AndroidStudio自带的Android Profiler、MAT等工具可以进行内存分析;手机端也有类似的内存分析app:leakcanary

leakCanary是Square开源框架,是一个Android和Java的内存泄露检测库,,集成sdk后,就会生成一个辅助应用,名字叫Leaks,
当Leakcanary检测到某个 activity 有内存泄露,会以通知栏形式报出,打开Leaks,就能看到具体函数以及代码行数

优点针对Android Activity组件完全自动化的内存泄漏检查可定制一些行为(dump文件和leaktrace对象的数量、自定义例外、分析结果的自定义处理等)集成到自己工程并使用的成本很低友好的界面展示和通知 缺点不能进行ANR检测,不过有另一款类似的app:BlockCanary

【安卓学习之第三方库】 Tencent Matrix-android使用-ANR

; █ Matrix-android 的使用

  1. 根目录下的build.gradle文件中添加依赖:
buildscript {
    ext {
        MATRIX_VERSION='2.0.0'
    }
    repositories {
        google()
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.1"
        classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}")

    }
}

allprojects {
    repositories {
        google()
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}
  1. APP目录下的build.gradle中添加依赖
dependencies {
    implementation "com.tencent.matrix:matrix-android-lib:${MATRIX_VERSION}"
    implementation "com.tencent.matrix:matrix-trace-canary:${MATRIX_VERSION}"
}

apply plugin: 'com.tencent.matrix-plugin'
matrix {
    trace {
        enable = true
        baseMethodMapFile = "${project.buildDir}/matrix_output/Debug.methodmap"
        blackListFile = "${project.projectDir}/matrixTrace/blackMethodList.txt"
    }
}

  1. Application中初始化
    @Override
    public void onCreate() {
        super.onCreate();
        Matrix.Builder builder = new Matrix.Builder(this);
        builder.pluginListener(new TestPluginListener(this));
        DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo();

        TraceConfig traceConfig = new TraceConfig.Builder()
                .dynamicConfig(dynamicConfig)

                .enableFPS(dynamicConfig.isFPSEnable())
                .enableEvilMethodTrace(dynamicConfig.isTraceEnable())
                .enableAnrTrace(dynamicConfig.isTraceEnable())
                .enableStartup(dynamicConfig.isTraceEnable())

                .splashActivities("com.bx.bxanr.MainActivity;")

                .isDebug(true)

                .isDevEnv(false)
                .build();

        TracePlugin tracePlugin = new TracePlugin(traceConfig);
        builder.plugin(tracePlugin);

        Matrix.init(builder.build());

        tracePlugin.start();
    }
  1. ANR监听事件 TestPluginListener:
public class TestPluginListener extends DefaultPluginListener {
    public static final String TAG = "TestPluginListener99";
    public SoftReference<Context> softReference;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    public TestPluginListener(Context context) {
        super(context);
        softReference = new SoftReference<>(context);
    }

    @Override
    public void onReportIssue(Issue issue) {
        super.onReportIssue(issue);
        MatrixLog.e(TAG, issue.toString());
        Log.e(TAG, issue.toString());

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Context context = softReference.get();
                String message = String.format("666 Report an issue - [%s]. context - [%s]", issue.getTag(),context);
                Log.e(TAG, message);
                if (context != null) {
                    Toast.makeText(context, message, Toast.LENGTH_LONG).show();
                }
            }
        });

    }

}
  1. 生成一个ANR事件:
        findViewById(R.id.test_anr_ImageButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testANR();
            }
        });
    protected void testANR() {
        try {
            var1 = 0;
            while (var1++ < 15) {
                Log.e("TestPluginListener", "try main sleep for make a test anr! try:" + var1 + "/15 , kill it if you don't want to wait!");
                try {
                    Thread.sleep(5000L);
                } catch (InterruptedException var2) {
                    var2.printStackTrace();
                    Log.e("TestPluginListener22", "Throwable:" + var2.getMessage());
                }
            }

        } catch (Throwable var2) {
            var2.printStackTrace();
            Log.e("TestPluginListener33", "Throwable:" + var2.getMessage());
        }
    }
  1. 打印的日志信息:
    可以看出是【at com.bx.bxanr.MainActivity:testANR(39)】出问题

E/TestPluginListener: try main sleep for make a test anr! try:1/10 , kill it if you don't want to wait!

I/Matrix.DeviceUtil: getTotalMemory cost:4, total_mem:2987102208, LowMemoryThresold:226492416, Memory Class:192
I/Matrix.DeviceUtil: [getLevel] totalMemory:2987102208 coresNum:8
I/Matrix.DeviceUtil: getLevel, cost:15, level:MIDDLE
I/default_matrix_: type=1400 audit(0.0:2919): avc: denied { read } for name="stat" dev="proc" ino=4026532302 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=1
I/default_matrix_: type=1400 audit(0.0:2920): avc: denied { open } for path="/proc/stat" dev="proc" ino=4026532302 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=1
I/Matrix.DeviceUtil: getAppCpuRate cost:33,rate:8.774502021974309E-4
I/Matrix.DefaultPluginListener: report issue content: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":8.774502021974309E-4,"mem":2987102208,"mem_free":1448560,"detail":"LAG","scene":"com.bx.bxanr.MainActivity","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","isProcessForeground":true,"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828350594}]

E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":8.774502021974309E-4,"mem":2987102208,"mem_free":1448560,"detail":"LAG","scene":"com.bx.bxanr.MainActivity","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","isProcessForeground":true,"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828350594}]
E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":8.774502021974309E-4,"mem":2987102208,"mem_free":1448560,"detail":"LAG","scene":"com.bx.bxanr.MainActivity","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","isProcessForeground":true,"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828350594}]
E/Matrix.AnrTracer: happens lag : {"machine":"MIDDLE","cpu_app":8.774502021974309E-4,"mem":2987102208,"mem_free":1448560,"detail":"LAG","scene":"com.bx.bxanr.MainActivity","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","isProcessForeground":true,"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828350594}
E/TestPluginListener: try main sleep for make a test anr! try:2/10 , kill it if you don't want to wait!

I/Matrix.AppMethodBeat: [copyData] [14152:14161] length:10 cost:0ms
W/Matrix.TraceDataUtils: [structuredDataToStack] has never out method[2], isIn:true, inTime:26295280, endTime:26300284,rawData size:3
W/Matrix.TraceDataUtils: [structuredDataToStack] has never out method[2], isIn:true, inTime:26295280, endTime:26300284,rawData size:2
W/Matrix.TraceDataUtils: [structuredDataToStack] has never out method[7308], isIn:true, inTime:26295280, endTime:26300284,rawData size:1
W/Matrix.TraceDataUtils: [structuredDataToStack] has never out method[1048574], isIn:true, inTime:26295280, endTime:26300284,rawData size:0
I/Matrix.TraceDataUtils: stackToTree: count=7
W/Matrix.AnrTracer: -
    >>>>>>>>>>>>>>>>>>>>>>> maybe happens ANR(5004 ms)! <<<<<<<<<<<<<<<<<<<<<<<
    |* [Status]
    |*      Scene: com.bx.bxanr.MainActivity
    |*      Foreground: true
    |*      Priority: 10    Nice: -10
    |*      is64BitRuntime: true
    |* [Memory]
    |*      DalvikHeap: 10858kb
    |*      NativeHeap: 10365kb
    |*      VmSize: 4351716kb
    |* [doFrame]
    |*      inputCost:animationCost:traversalCost
    |*      0:0:0
    |* [Thread]
    |*      Stack(TIMED_WAITING):
    |*      at com.bx.bxanr.MainActivity:testANR(39)
    |*      at com.bx.bxanr.MainActivity$2:onClick(25)
    |*      at android.view.View:performClick(6294)
    |*      at com.google.android.material.button.MaterialButton:performClick(1119)
    |*      at android.view.View$PerformClick:run(24774)
    |*      at android.os.Handler:handleCallback(790)
    |*      at android.os.Handler:dispatchMessage(99)
    |*      at android.os.Looper:loop(164)
    |*      at android.app.ActivityThread:main(6518)
    |* [Trace]
    |*      StackKey: 2|
    |*      TraceStack:
    |*      [id count cost]
    |*      1048574 1 5004
    |*      .7308 1 5004
    |*      ..7306 1 0
    |*      ...7305 1 0
    |*      ....7309 1 0
    |*      ..2 1 5004
    |*      ...2 1 5004
    =========================================================================
    postTime:26295280 curTime:26300284
I/Matrix.DeviceUtil: getAppCpuRate cost:20,rate:9.488731868654589E-4
I/Matrix.DefaultPluginListener: report issue content: tag[Trace_EvilMethod]type[0];key[26295280334291];content[{"machine":"MIDDLE","cpu_app":9.488731868654589E-4,"mem":2987102208,"mem_free":1446552,"detail":"ANR","cost":5004,"stackKey":"2|","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,5004\n1,7308,1,5004\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,5004\n3,2,1,5004\n","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","processPriority":10,"processNice":-10,"isProcessForeground":true,"memory":{"dalvik_heap":10858,"native_heap":10365,"vm_size":4351716},"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828353601}]

E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[26295280334291];content[{"machine":"MIDDLE","cpu_app":9.488731868654589E-4,"mem":2987102208,"mem_free":1446552,"detail":"ANR","cost":5004,"stackKey":"2|","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,5004\n1,7308,1,5004\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,5004\n3,2,1,5004\n","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","processPriority":10,"processNice":-10,"isProcessForeground":true,"memory":{"dalvik_heap":10858,"native_heap":10365,"vm_size":4351716},"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828353601}]

E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[26295280334291];content[{"machine":"MIDDLE","cpu_app":9.488731868654589E-4,"mem":2987102208,"mem_free":1446552,"detail":"ANR","cost":5004,"stackKey":"2|","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,5004\n1,7308,1,5004\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,5004\n3,2,1,5004\n","threadStack":" \nat com.bx.bxanr.MainActivity:testANR(39)\nat com.bx.bxanr.MainActivity$2:onClick(25)\nat android.view.View:performClick(6294)\nat com.google.android.material.button.MaterialButton:performClick(1119)\nat android.view.View$PerformClick:run(24774)\nat android.os.Handler:handleCallback(790)\nat android.os.Handler:dispatchMessage(99)\nat android.os.Looper:loop(164)\nat android.app.ActivityThread:main(6518)\n","processPriority":10,"processNice":-10,"isProcessForeground":true,"memory":{"dalvik_heap":10858,"native_heap":10365,"vm_size":4351716},"tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828353601}]
E/TestPluginListener: try main sleep for make a test anr! try:3/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:4/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:5/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:6/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:7/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:8/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:9/10 , kill it if you don't want to wait!

E/TestPluginListener: try main sleep for make a test anr! try:10/10 , kill it if you don't want to wait!

I/Matrix.AppMethodBeat: [copyData] [14152:14165] length:14 cost:0ms
I/Matrix.TraceDataUtils: stackToTree: count=7
I/Choreographer: Skipped 3001 frames!  The application may be doing too much work on its main thread.

W/Matrix.EvilMethodTracer: -
    >>>>>>>>>>>>>>>>>>>>> maybe happens Jankiness!(50010ms) <<<<<<<<<<<<<<<<<<<<<
    |* [Status]
    |*      Scene: com.bx.bxanr.MainActivity
    |*      Foreground: true
    |*      Priority: 10    Nice: -10
    |*      is64BitRuntime: true
    |*      CPU: 0.01%
    |* [doFrame]
    |*      inputCost:animationCost:traversalCost
    |*      3355573:1188177:3037395
    |*      StackKey: 2|
    |*      TraceStack:
    |*      [id count cost]
    |*      1048574 1 50011
    |*      .7308 1 50007
    |*      ..7306 1 0
    |*      ...7305 1 0
    |*      ....7309 1 0
    |*      ..2 1 50007
    |*      ...2 1 50007
    =========================================================================
I/Matrix.DeviceUtil: getAppCpuRate cost:20,rate:0.0012852167232400029

E/TestPluginListener99: 666 Report an issue - [Trace_EvilMethod]. context - [com.bx.bxanr.BxANRApp@9751672]
I/Matrix.DefaultPluginListener: report issue content: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":0.0012852167232400029,"mem":2987102208,"mem_free":1451928,"detail":"NORMAL","cost":50011,"usage":"0.01%","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,50011\n1,7308,1,50007\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,50007\n3,2,1,50007\n","stackKey":"2|","tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828398594}]

E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":0.0012852167232400029,"mem":2987102208,"mem_free":1451928,"detail":"NORMAL","cost":50011,"usage":"0.01%","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,50011\n1,7308,1,50007\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,50007\n3,2,1,50007\n","stackKey":"2|","tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828398594}]
E/TestPluginListener99: tag[Trace_EvilMethod]type[0];key[null];content[{"machine":"MIDDLE","cpu_app":0.0012852167232400029,"mem":2987102208,"mem_free":1451928,"detail":"NORMAL","cost":50011,"usage":"0.01%","scene":"com.bx.bxanr.MainActivity","stack":"0,1048574,1,50011\n1,7308,1,50007\n2,7306,1,0\n3,7305,1,0\n4,7309,1,0\n2,2,1,50007\n3,2,1,50007\n","stackKey":"2|","tag":"Trace_EvilMethod","process":"com.bx.bxanr","time":1630828398594}]

E/TestPluginListener99: 666 Report an issue - [Trace_EvilMethod]. context - [com.bx.bxanr.BxANRApp@9751672]
E/TestPluginListener99: 666 Report an issue - [Trace_EvilMethod]. context - [com.bx.bxanr.BxANRApp@9751672]

█ 遇到的问题

█ 相关资料

提示:以下是相关文章以供参考

[En]

Tip: here are the related articles for reference

  1. 官方项目地址:Matrix-android
  2. Android SDK 使用指南 – Bugly 文档
  3. 2019.05.10 Android 微信APM工具 Matrix使用 – 简书
  4. 2020-12-31 使用bugly没有ANR上报? – 问答 – 云+社区 – 腾讯云:一加6T,Android 9,抓不到ANR,
  5. 重点:2019.04.30 Android CRASH ANR 日志收集 – 简书:Android6.0后的设备没系统权限,无法上传ANR信息(/data/system/dropbox/trace.txt)
  6. 2019.10.29 APP测试之CRASH|| ANR – 简书:举例空指针、 数组越界、内存溢出、非UI线程操作UI线程、类型转换、遍历数组的时候不能进行增删改操作、数据库关闭的状态下,强行打开、ANR的产生原因等
  7. 2017-06-08【Android端ANR卡顿检测】BlockCanary检测 – 可可_小虾米 – 博客园

█ 免责声明

所有博主分享的文章内容,有的参考网络教程,有的引用大神高的理论,有的做法,记笔记,内容中可能有很多不准确之处,但也希望海涵,本内容仅供学习研究之用,请勿用于商业目的,如果您是作者的部分内容,不喜欢本内容分享,可以联系博主说明相关情况通知删除,谢谢您的理解和支持!

[En]

The content of all the articles shared by bloggers, some refer to online tutorials, quote the great god Gao theory, some practice, write down notes, there may be many inaccuracies in the content, but also hope Haihan, this content is only for study and research use, do not use for commercial purposes, if you are the author of part of the content, do not like this content to be shared, you can contact the blogger to explain the relevant situation notice deletion, thank you for your understanding and support!

提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/120112498

Original: https://blog.csdn.net/ljb568838953/article/details/120112498
Author: 笔夏
Title: 【安卓学习之第三方库】 Tencent Matrix-android使用-ANR

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/512247/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球