系统应用集成 LeakCanary

本文介绍如何在系统应用中集成LeakCanary。由于很多系统应用不使用gradle,且通过Android.mk来进行编译,因此无法使用类似gradle的方式添加依赖来完成对LeakCanary的集成和使用。

1. 源码下载

LeakCanary的源码链接 https://github.com/square/leakcanary,通过 git clone 或者 zip 的方式将源码下载到本地,源码目录如下:
系统应用集成 LeakCanary_第1张图片
leakcanary-analyzerleakcanary-androidleakcanary-watcher 复制到系统应用源码根目录下。

2. 添加编译支持(修改Android.mk)

将上述3个java代码目录添加到编译树中:

LOCAL_SRC_FILES += $(call all-java-files-under, leakcanary-analyzer/) \
                   $(call all-java-files-under, leakcanary-android/) \
                   $(call all-java-files-under, leakcanary-watcher/)

将 leakcanary-android 目录下的 res 目录添加到资源文件编译:

LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/leakcanary-android/src/main/res

添加 hahatrove 的 jar 包到系统应用源码 libs 文件夹中,haha-2.0.3.jar 和 trove-3.0.2.jar 的下载链接:

https://pan.baidu.com/s/1dto2NcgvxEdiA3lGXVKX0A 提取码: qjqy

将这两个 jar 包加入编译:

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += \
				haha:libs/haha-2.0.3.jar \
				trove:libs/trove-3.0.2.jar

LOCAL_STATIC_JAVA_LIBRARIES += \
               haha \
               trove

3. 修改 AndroidManifest.xml

需要将 leakcanary-android 中声明的 Activity,Service,Provider 等组件以及权限申请加入到 AndroidManifest.xml 清单文件中:










       


        
            
            
        


4. 初始化 LeakCanary

在应用 Application (如果没有,需要手写一个并在 AndroidManifest.xml 文件中注册)的 onCreate 函数中初始化 LeakCanary。

@Override
public void onCreate() {
    super.onCreate();
    if (!LeakCanary.isInAnalyzerProcess(this)) {
        sRefWatcher = LeakCanary.install(this);
    }
}

5. 其他编译错误解决

packages/apps/****/leakcanary-android/src/main/res/values/leak_canary_public.xml:19: error: No 'id' attribute supplied , and no previous id defined in this file.
packages/apps/****/leakcanary-android/src/main/res/values/leak_canary_public.xml:20: error: No 'id' attribute supplied , and no previous id defined in this file.
packages/apps/****/leakcanary-android/src/main/res/values/leak_canary_public.xml:21: error: No 'id' attribute supplied , and no previous id defined in this file.

解决方法:直接删除 leak_canary_public.xml。

packages/apps/****/leakcanary-analyzer/src/main/java/com/squareup/leakcanary/HeapAnalyzer.java:31: 错误: 找不到符号
import gnu.trove.THashMap;
packages/apps/****/leakcanary-analyzer/src/main/java/com/squareup/leakcanary/HeapAnalyzer.java:32: 错误: 找不到符号
import gnu.trove.TObjectProcedure;

解决方法:在 HeapAnalyzer.java 文件中将 “import gnu.trove.THashMap” 修改成 “import gnu.trove.map.hash.THashMap”,将 “import gnu.trove.TObjectProcedure” 修改成 “import gnu.trove.procedure.TObjectProcedure”。

packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:22: 错误: 程序包org.junit不存在
import org.junit.Before;
                ^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:23: 错误: 程序包org.junit不存在
import org.junit.Test;
                ^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:24: 错误: 程序包org.junit.runner不存在
import org.junit.runner.RunWith;
                       ^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:25: 错误: 程序包org.junit.runners不存在
import org.junit.runners.Parameterized;
                        ^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:34: 错误: 程序包org.hamcrest.core不存在
import static org.hamcrest.core.StringContains.containsString;
                               ^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:34: 错误: 仅从类和接口静态导入
import static org.hamcrest.core.StringContains.containsString;
^
packages/apps/****/leakcanary-analyzer/src/test/java/com/squareup/leakcanary/AsyncTaskLeakTest.java:35: 错误: 程序包org.junit不存在
import static org.junit.Assert.assertEquals;

解决方法:直接删除所有的 Test 类文件

packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/DisplayLeakService.java:57: 错误: 程序包R不存在
      String contentTitle = getString(R.string.leak_canary_no_leak_title);
                                       ^
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/DisplayLeakService.java:58: 错误: 程序包R不存在
      String contentText = getString(R.string.leak_canary_no_leak_text);

解决办法:将 LeakCanary 中所有使用到 “R” 的地方都替换成 import 当前系统应用的 “R”。

import static com.squareup.leakcanary.BuildConfig.GIT_SHA;
                                     ^
  符号:   类 BuildConfig
  位置: 程序包 com.squareup.leakcanary
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:30: 错误: 仅从类和接口静态导入
import static com.squareup.leakcanary.BuildConfig.GIT_SHA;
^
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:31: 错误: 找不到符号
import static com.squareup.leakcanary.BuildConfig.LIBRARY_VERSION;
                                     ^
  符号:   类 BuildConfig
  位置: 程序包 com.squareup.leakcanary
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:31: 错误: 仅从类和接口静态导入
import static com.squareup.leakcanary.BuildConfig.LIBRARY_VERSION;
^

解决方法:在 leakcanary-android/src/main/java/com/squareup/leakcanary/ 文件夹下创建一个 BuildConfig.java 文件,在其中添加如下内容:public static String GIT_SHA = "GIT_SHA"; public static String LIBRARY_VERSION = "LIBRARY_VERSION";

packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/AndroidOFragmentRefWatcher.java:22: 错误: 找不到符号
import android.support.annotation.RequiresApi;
                                 ^
  符号:   类 RequiresApi
  位置: 程序包 android.support.annotation
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/AndroidOFragmentRefWatcher.java:27: 错误: 找不到符号
@RequiresApi(Build.VERSION_CODES.O) //

解决方法:去除 RequiresApi 注解及相关的 import。

packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/AbstractAnalysisResultService.java:47: 错误: 找不到符号
    ContextCompat.startForegroundService(context, intent);
                 ^
  符号:   方法 startForegroundService(Context,Intent)
  位置: 类 ContextCompat
packages/apps/****/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/HeapAnalyzerService.java:49: 错误: 找不到符号
    ContextCompat.startForegroundService(context, intent);
                 ^
  符号:   方法 startForegroundService(Context,Intent)
  位置: 类 ContextCompat

解决方法:将 “ContextCompat.startForegroundService(context, intent)” 修改成 context.startForegroundService(intent)

你可能感兴趣的:(Android)