1. 程式人生 > >Android系統App中使用Leakcanary

Android系統App中使用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:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := samples

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR += $(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 += $(LOCAL_PATH)/../leakcanary-1.5/leakcanary-android/src/main/res LOCAL_SRC_FILES += $(call all-java-files-under, ../leakcanary-1.5/leakcanary-analyzer/src/main/java) LOCAL_SRC_FILES += $(call all-java-files-under, ../leakcanary-1.5/leakcanary-android/src/main/java) LOCAL_SRC_FILES += $(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 $(CLEAR_VARS) LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libhaha:../leakcanary-1.5/libs/haha-2.0.3.jar include $(BUILD_MULTI_PREBUILT) # Use the following include to make our test apk. include $(call all-makefiles-under,$(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 <public>, 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 <public>, 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 <public>, 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)'
    at com.android.sched.scheduler.ScheduleInstance.runWithLog(ScheduleInstance.java:163)
    at com.android.sched.scheduler.MultiWorkersScheduleInstance$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 [email protected])).
Warning: This may have produced partial or corrupted output.

需要在mk裡關掉程式碼混淆,LOCAL_PROGUARD_ENABLED := disabled

2. 修改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>

3. 修改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字串的檔案,再重新抓取一次。

相關推薦

Android系統App使用Leakcanary

由於最新的v1.5.1支援到了O版本,使用了O版本的API,在N上各種編譯錯誤,所以本文用到的版本是v1.5。下載地址 本文以development/samples/HelloActivity為示例。, 包含本文提到的所以檔案。 將Leakcanary

android系統原始碼新增app原始碼(原始碼部署移植)

涉及到系統定製,需要在系統中加入自己的apk工程,但是上網找了很多資料都是不夠全面的,或者看了還是沒搞懂,我自己也是一點點摸索過來的,花了不少的時間,也是踩了不少的坑,因此特開一文,幫助大家渡河。 申明,本文親測有效,如果有疑問,歡迎在下方留言。人人為我,我為

Android系統APP之SettingsProvider

Android系統APP之SettingsProvider SettingsProvider顧名思義是一個提供設定資料共享的Provider     SettingsProvider只接受int、float、string等基本型別的資料;   

Android Module app 訪問不到libs包的class類

在Android studio 3.0 之前新建一個App,新建一個Libs庫,App引用Libs庫,compile project(':xxxLib'); App就可以引用Libs 中的資源了 但是

android系統app開啟藍芽+設定可見性

   BluetoothAdapter blue = BluetoothAdapter.getDefaultAdapter();     這兩個方法足矣滿足你的需求(需要system許可權):    

Android系統APP安裝流程

更多內容,歡迎關注公眾號:tmac_lover 這篇文章介紹一下Android裡安裝一個apk檔案的完整流程,我們以pm install安裝一個新的app為例介紹。 1. pm命令 當我們使用 pm install -r /sdcard/t

Android程序守護,讓APP系統記憶體常駐(一)

       其實我們開發者並不想讓自己做的應用變成流氓軟體,但是沒辦法, 你的老闆需要,你要不想讓你的應用常駐,那咱就常駐不了了。。。所以說,言歸正傳。。。       第一篇準備使用系統的服務保活。如果想看提高app的程序等級來實現應用保活,可以直接進行點選Androi

Android程序守護,讓APP系統記憶體常駐(二)

      昨天晚上寫了用系統服務等方法來實現應用保活。今天寫一下用提高app的程序等級來實現應用保活。想看直接呼叫系統方法保活應用的可以點選Android程序守護,讓APP在系統記憶體中常駐(一)進行跳轉。       一:第一種實現思路,建立廣播接收者來監聽系統關屏亮屏

如何在自己的App呼叫Android系統自帶的安裝/解除安裝程式

AppUtils裡面寫了如何安裝和解除安裝apk(這段程式碼出自這裡:點選開啟連結~),這裡的安裝和解除安裝呼叫的是Android本身的一個安裝解除安裝,所以可能頁面不會太優雅,並不符合商業App的期望,如果要做到更優雅的實現,就要用到靜默安裝/解除安裝,這個可以參照網上教

Android如何在app通過一個按鈕直接跳轉到的系統的許可權設定頁面

續上一篇《Android的許可權設定及自啟動設定》,在開發中我通過一個按鈕來進行跳轉到系統的許可權頁面,一開始的程式碼就是上一篇中的原模原樣的程式碼,如下所示: /** * 跳轉到許可權設定介面 */ private void getAppDetailSettingInt

(備忘)Android app呼叫啟動其他應用(系統應用和第三方應用)

一、開啟第三方應用 方法一 Intent intent=new Intent(); //包名 包名+類名(全路徑) intent.setClassName("com.linxcool", "com.linxcool.PlaneAct

使用VS2017開發APP使用VUE.js開發遇到打包出來的android文件 在低版本的android(4.3)無法正常使用

vue.js 文件 默認 項目 let ons dir file 開發app 使用VS2017開發VUE的APP應用遇到的問題集合 1, 打包出來的apk文件在Android 6.0版本以上手機可以正常打開,在Android 4.3版本手機上無法打開 原因:一開

android將應用圖片保存到系統相冊並顯示

context sca new 場景 adc finally sep r+ ace 我應用到的場景是程序中在視頻通訊時截圖,將截圖保存到本地相冊中 /*** @param bmp 獲取的bitmap數據 * @param picName 自定義的圖片名*/ public

APP關於Android和IOS與網頁交互

frame win android rem androi create out eth sta 安卓交互: //安卓js代碼start function bntcat(){ if(isAndroid){ musicP

必須做作業三:某Android端點餐App觀察者模式解析

onclick https 直接 tro lstat strong set lis drag 該項目還在開發中,目前開發了原型界面,是為了實現顧客從點餐到付款的全行為流程。並且提供菜品的詳情頁面和其他服務接口。 在此就以點餐界面的實現為例,分析該項目的觀察者模式 一、模

Android Studio 編寫系統APP

現狀 現在Android Studio正在變得越來越流行,幾乎所有的APP開發者都開始使用Android Studio, 那我們如何才能夠在AS裡呼叫自己的framework.jar而不是SDK裡的呢。 問題 當我們需要寫一些系統內建的APP時,比如Launcher, Setting

iOS App一個檢視從新增到完全渲染,在這個過程,iOS系統都做了什麼?

文字簡答: 首先一個檢視由CPU進行Frame佈局,準備檢視和圖層的層級關係,查詢是否有重寫drawRect:或drawLayer:inContext:方法,注意:如果有重寫的話,這裡的渲染是會佔用CPU進行處理的。 CPU會將處理檢視和圖層的層級關係

Eclipse新增Android系統jar包

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android中將應用裝到/system/app

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android系統main.mk關於RCS和SCCS的解釋

# this turns off the RCS / SCCS implicit rules of GNU Make % : RCS/%,v % : RCS/% % : %,v % : s.% % : S