转载自:http://blog.csdn.net/abc_1234d/article/details/72478385
Leakcanary主页
由于最新的v1.5.1支持到了O版本,使用了O版本的API,在N上各种编译错误,所以本文用到的版本是v1.5。下载地址
本文以development/samples/HelloActivity为示例。示例下载地址,
包含本文提到的所以文件。
将Leakcanary文件夹放到development/samples目录,需要修改HelloActivity的Android.mk、AndroidManifest.xml和对应的Application.java
由于依赖haha这个库,所以需要另外下载 下载地址
放到leakcanary工程的libs目录下。在示例代码中已经包含。
准备好就开动吧。
1.修改Android.mk
LOCAL_PATH:= (callmy−dir)include ( c a l l m y − d i r ) i n c l u d e (CLEAR_VARS)
LOCAL_MODULE_TAGS := samples
Only compile source java files in this apk.
LOCAL_SRC_FILES :=
(callall−java−files−under,src)LOCALRESOURCEDIR+=
(
c
a
l
l
a
l
l
−
j
a
v
a
−
f
i
l
e
s
−
u
n
d
e
r
,
s
r
c
)
L
O
C
A
L
R
E
S
O
U
R
C
E
D
I
R
+
=
(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS := –auto-add-overlay
LOCAL_AAPT_FLAGS += –extra-packages com.squareup.leakcanary
LOCAL_STATIC_JAVA_LIBRARIES += libhaha
LOCAL_RESOURCE_DIR +=
(LOCALPATH)/../leakcanary−1.5/leakcanary−android/src/main/resLOCALSRCFILES+=
(
L
O
C
A
L
P
A
T
H
)
/
.
.
/
l
e
a
k
c
a
n
a
r
y
−
1.5
/
l
e
a
k
c
a
n
a
r
y
−
a
n
d
r
o
i
d
/
s
r
c
/
m
a
i
n
/
r
e
s
L
O
C
A
L
S
R
C
F
I
L
E
S
+
=
(call all-java-files-under, ../leakcanary-1.5/leakcanary-analyzer/src/main/java)
LOCAL_SRC_FILES +=
(callall−java−files−under,../leakcanary−1.5/leakcanary−android/src/main/java)LOCALSRCFILES+=
(
c
a
l
l
a
l
l
−
j
a
v
a
−
f
i
l
e
s
−
u
n
d
e
r
,
.
.
/
l
e
a
k
c
a
n
a
r
y
−
1.5
/
l
e
a
k
c
a
n
a
r
y
−
a
n
d
r
o
i
d
/
s
r
c
/
m
a
i
n
/
j
a
v
a
)
L
O
C
A
L
S
R
C
F
I
L
E
S
+
=
(call all-java-files-under, ../leakcanary-1.5/leakcanary-watcher/src/main/java)
LOCAL_SRC_FILES += $(call all-java-files-under, ../leakcanary-1.5/leakcanary-android-gen/src/main/java)
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_PACKAGE_NAME := HelloActivity
LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
include (CLEARVARS)LOCALPREBUILTSTATICJAVALIBRARIES:=libhaha:../leakcanary−1.5/libs/haha−2.0.3.jarinclude ( C L E A R V A R S ) L O C A L P R E B U I L T S T A T I C J A V A L I B R A R I E S := l i b h a h a : . . / l e a k c a n a r y − 1.5 / l i b s / h a h a − 2.0.3. j a r i n c l u d e (BUILD_MULTI_PREBUILT)
Use the following include to make our test apk.
include (callall−makefiles−under, ( c a l l a l l − m a k e f i l e s − u n d e r , (LOCAL_PATH))
修改Android.mk,编译后会报几个错误。
资源错误,直接删除leak_canary_public.xml。
development/samples/HelloActivity/../leakcanary-1.5/leakcanary-android/src/main/res/values/leak_canary_public.xml:19: error: No ‘id’ attribute supplied , and no previous id defined in this file.
development/samples/HelloActivity/../leakcanary-1.5/leakcanary-android/src/main/res/values/leak_canary_public.xml:20: error: No ‘id’ attribute supplied , and no previous id defined in this file.
development/samples/HelloActivity/../leakcanary-1.5/leakcanary-android/src/main/res/values/leak_canary_public.xml:21: error: No ‘id’ attribute supplied , and no previous id defined in this file.
找不到BuildConfig、LIBRARY_VERSION 和GIT_SHA。
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/DisplayLeakActivity.java:66: The import com.squareup.leakcanary.BuildConfig cannot be resolved
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/DisplayLeakActivity.java:67: The import com.squareup.leakcanary.BuildConfig cannot be resolved
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/DisplayLeakActivity.java:271: LIBRARY_VERSION cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/internal/DisplayLeakActivity.java:273: GIT_SHA cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:28: The import com.squareup.leakcanary.BuildConfig cannot be resolved
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:29: The import com.squareup.leakcanary.BuildConfig cannot be resolved
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:95: LIBRARY_VERSION cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:95: GIT_SHA cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:121: LIBRARY_VERSION cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/leakcanary-1.5/leakcanary-android/src/main/java/com/squareup/leakcanary/LeakCanary.java:123: GIT_SHA cannot be resolved to a variable
ERROR: /work2/mtk6737_N_gerrit/development/samples/HelloActivity/src/com/example/android/helloactivity/HelloActivity.java:38: hello_activity cannot be resolved or is not a field
BuildConfig是在IDE进行编译生成的,因此只能手动创建一个BuildConfig.java。在leakcanary工程新建一个leakcanary-android-gen/src/main/java/com/squareup/leakcanary目录,接着新建一个BuildConfig.java。
内容包含以下代码 (没研究过这个两个字符串的影响,随意赋值了):
package com.squareup.leakcanary;
public final class BuildConfig {
public static String GIT_SHA = “GIT_SHA”;
public static String LIBRARY_VERSION = “LIBRARY_VERSION”;
}
记得修改Android.mk,添加LOCAL_SRC_FILES += $(call all-java-files-under,../leakcanary-1.5/leakcanary-android-gen/src/main/java
报RunnerProcessException。
com.android.sched.scheduler.RunnerProcessException: Error during ‘TypeGenericSignatureSplitter’ runner on ‘class com.squareup.haha.guava.collect.AbstractMapBasedMultimap
WrappedSortedSet(AbstractMapBasedMultimap.java:0−0)′atcom.android.sched.scheduler.ScheduleInstance.runWithLog(ScheduleInstance.java:163)atcom.android.sched.scheduler.MultiWorkersScheduleInstance
W
r
a
p
p
e
d
S
o
r
t
e
d
S
e
t
(
A
b
s
t
r
a
c
t
M
a
p
B
a
s
e
d
M
u
l
t
i
m
a
p
.
j
a
v
a
:
0
−
0
)
′
a
t
c
o
m
.
a
n
d
r
o
i
d
.
s
c
h
e
d
.
s
c
h
e
d
u
l
e
r
.
S
c
h
e
d
u
l
e
I
n
s
t
a
n
c
e
.
r
u
n
W
i
t
h
L
o
g
(
S
c
h
e
d
u
l
e
I
n
s
t
a
n
c
e
.
j
a
v
a
:
163
)
a
t
c
o
m
.
a
n
d
r
o
i
d
.
s
c
h
e
d
.
s
c
h
e
d
u
l
e
r
.
M
u
l
t
i
W
o
r
k
e
r
s
S
c
h
e
d
u
l
e
I
n
s
t
a
n
c
e
SequentialTask.process(MultiWorkersScheduleInstance.java:442)
at com.android.sched.scheduler.MultiWorkersScheduleInstance$Worker.run(MultiWorkersScheduleInstance.java:162)
Caused by: java.lang.reflect.GenericSignatureFormatError
at com.android.jack.signature.GenericSignatureParser.expect(GenericSignatureParser.java:371)
at com.android.jack.signature.GenericSignatureParser.parseClassTypeSignature(GenericSignatureParser.java:236)
at com.android.jack.signature.GenericSignatureParser.parseClassSignature(GenericSignatureParser.java:136)
at com.android.jack.signature.GenericSignatureParser.parseClassSignature(GenericSignatureParser.java:99)
at com.android.jack.transformations.ast.string.TypeGenericSignatureSplitter.getSplittedSignature(TypeGenericSignatureSplitter.java:70)
at com.android.jack.transformations.ast.string.TypeGenericSignatureSplitter.run(TypeGenericSignatureSplitter.java:47)
at com.android.jack.transformations.ast.string.TypeGenericSignatureSplitter.run(TypeGenericSignatureSplitter.java:37)
at com.android.sched.scheduler.ScheduleInstance.runWithLog(ScheduleInstance.java:161)
… 2 more
Internal compiler error (version 1.2-rc4 ‘Carnac’ (298900 f95d7bdecfceb327f9d201a1348397ed8a843843 by android-jack-team@google.com)).
Warning: This may have produced partial or corrupted output.
需要在mk里关掉代码混淆,LOCAL_PROGUARD_ENABLED := disabled
- 修改AndroidManifest.xml
需要注意几个点:
- 添加读写外部存储的权限,在安装应用后手动打开权限。
- 将新添加leakcanary的activity和service属性android:enabled修改为true
- 如果没有自定义application,需要手动创建一个。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.helloactivity">
<!-- To store the heap dumps and leak analysis results. -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:label="Hello, Activity!"
android:name="com.example.android.helloactivity.MyApp">
<activity android:name="HelloActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="com.squareup.leakcanary.internal.HeapAnalyzerService"
android:process=":leakcanary"
android:enabled="true"
/>
<service
android:name="com.squareup.leakcanary.DisplayLeakService"
android:enabled="true"
/>
<activity
android:theme="@style/leak_canary_LeakCanary.Base"
android:name="com.squareup.leakcanary.internal.DisplayLeakActivity"
android:enabled="true"
android:label="@string/leak_canary_display_activity_label"
android:icon="@drawable/leak_canary_icon"
android:taskAffinity="com.squareup.leakcanary"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:theme="@style/leak_canary_Theme.Transparent"
android:name="com.squareup.leakcanary.internal.RequestStoragePermissionActivity"
android:taskAffinity="com.squareup.leakcanary"
android:enabled="true"
android:icon="@drawable/leak_canary_icon"
android:label="@string/leak_canary_storage_permission_activity_label"
/>
</application>
</manifest>
- 修改Application
package com.example.android.helloactivity;
import android.app.Application;
import com.squareup.leakcanary.LeakCanary;
public class MyApp extends Application{
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
}
}
4.测试
在HelloActivity.java:onCreate()方法里添加
new Handler().postDelayed(new Runnable(){
public void run(){
new Handler().postDelayed(this, 1000);
}
}, 1000);
使Activity实例一直被Runnable持有,导致内存泄露。
打开应用后退出,过一会就会生成报告了。
有时候一直无法生成报告,输出如下log,
D LeakCanary: Could not dump heap, previous analysis still is in progress.
删除/sdcard/Download/leakcanary-com.example.android.helloactivity/目录下包含pending字符串的文件,再重新抓取一次。