一、介绍:
最近做app性能优化增加了几个第三方性能检测框架:
1、leakcanary(内存泄漏检测)
2、blockcanary(耗时检测工具)
因为项目开发时在android studio工具编译但在完整编译时是用make方式和整个项目一起编译,所以需要在AS编译时自动把上面性能检测工具编入方便开发自我调试,但在make编译版本不能带上上面工具(各种提示和日志影响用户体验),同时也要满足所有开发使用同一份代码互不影响,git库使用同一份代码大家都能用到上面功能。
针对上面情况需要差异化编译代码,并且兼容android studio和make脚本编译方式。
二、分析
1.leakcanary和blockcanary工具使用方法都只是需要在application类中做初始化即可,不涉及其它代码,所以需要对application进行差异化区分。
2.application需要在AndroidManifest.xml中声明,所以需要差异化AndroidManifest.xml文件。
3.添加leakcanary和blockcanary工具有两种方式:
(1)下载源码或jar包
(2)直接通过gradle引入
这两种方法都可以我选择的是第二种,因为添加上面工具主要是给开发自己使用所以需要和编译给其它人使用区分开,这个纪要用到多渠道打包方式。
4.make编译是给客户或测试的所以不需要编译上面工具,需要区分。
三、实施
根据以上分析我们需要做以下几个工作:
一.创建一个独立目录存放差异代码(这个目录不能在其它被包含的目录内否则可能会被其它代码编译进去)
我这里主要是需要application文件所以修改了上面几个文件res,libs等目录如果用到了也可以添加
1.因为项目开始没有重写application,所以新建了一个,如果之前已经重写了则需要在原来的基础上加上新增代码(保证原有功能)
import android.app.Application;
import android.content.Context;
import com.github.moduth.blockcanary.BlockCanary;
import com.squareup.leakcanary.LeakCanary;
public class LauncherApplication extends Application {
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
//耗时检测初始化
BlockCanary.install(this, new AppContext()).start();
//内存泄漏初始化
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);
}
public static Context getAppContext(){
return mContext;
}
}
2.下面是新增文件给BlockCanary配置参数
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.android.launcher3.util.RyLogger;
import com.github.moduth.blockcanary.BlockCanaryContext;
public class AppContext extends BlockCanaryContext {
private static final String TAG = "AppContext";
@Override
public String provideQualifier() {
String qualifier = "";
try {
PackageInfo info = LauncherApplication.getAppContext().getPackageManager()
.getPackageInfo(LauncherApplication.getAppContext().getPackageName(), 0);
qualifier += info.versionCode + "_" + info.versionName + "_YYB";
} catch (PackageManager.NameNotFoundException e) {
RyLogger.e(TAG, "provideQualifier exception"+e);
}
return qualifier;
}
@Override
public int provideBlockThreshold() {
//阻塞时间超过多少秒发通知
return 1000;
}
@Override
public boolean displayNotification() {
return true;
}
@Override
public boolean stopWhenDebugging() {
return false;
}
}
3.最后是AndroidManifest.xml文件同样需要保持原有代码并修改application,主要是替换application文件
<application
android:name=".LauncherApplication"
android:backupAgent=".LauncherBackupAgent"
android:fullBackupContent="@xml/backupscheme"
android:fullBackupOnly="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:label="@string/derived_app_name"
android:theme="@style/AppTheme"
android:largeHeap="@bool/config_largeHeap"
android:networkSecurityConfig="@xml/network_security_config"
android:restoreAnyVersion="true"
android:supportsRtl="true">
二.修改build.gradle
1.主要是添加代码差异化编译,新增的代码
//新增目录需要编译内容,src,res,libs,manifest
debug {
java.srcDirs = ['debug_src']
jniLibs.srcDirs = ['libs']
res.srcDirs = ['res']
manifest.srcFile "debug_src/AndroidManifest.xml"
}
sourceSets {
main {
res.srcDirs = ['res']
java.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
manifest.srcFile 'AndroidManifest-common.xml'
proto {
srcDir 'protos/'
srcDir 'proto_overrides/'
}
}
//新增目录需要编译内容,src,res,libs,manifest
debug {
java.srcDirs = ['debug_src']
jniLibs.srcDirs = ['libs']
res.srcDirs = ['res']
manifest.srcFile "debug_src/AndroidManifest.xml"
}
androidTest {
res.srcDirs = ['tests/res']
java.srcDirs = ['tests/src']
manifest.srcFile "tests/AndroidManifest-common.xml"
}
androidTestDebug {
manifest.srcFile "tests/AndroidManifest.xml"
}
aosp {
java.srcDirs = ['src_flags', "src_ui_overrides"]
}
}
2.添加引入方式
当前使用了两种方式一种时jar包一种是Implementation引入
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
// Optional, if you use support library fragments:
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1'
}
三、make文件差异化编译
1.如果需要增加新工具到make中需要做以下工作
include $(CLEAR_VARS)
LOCAL_MODULE := blockcanary #别名
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_SRC_FILES := libs/blockcanary.jar #包名
LOCAL_UNINSTALLABLE_MODULE := true
#LOCAL_SDK_VERSION := current
LOCAL_PRIVATE_PLATFORM_APIS:=true
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := libxypatch3
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES_32 := libs/armeabi/libxypatch.so
LOCAL_SRC_FILES_64 := libs/arm64-v8a/libxypatch.so
LOCAL_MULTILIB := both
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
include $(BUILD_PREBUILT)
LOCAL_STATIC_JAVA_LIBRARIES += blockcanary \ libxypatch3 #加入静态库
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, src_ui_overrides) \
$(call all-java-files-under, src_flags) \
$(call all-proto-files-under, protos) \
$(call all-proto-files-under, debug_src/src) #新增
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/debug_src/res #新增
LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/debug_src/AndroidManifest-common.xml #新增
2.如果不需要添加到make编译中
需要注意新增的debug_src目录是否被之前编译目录包含如果已经被包含则需要移动到其它目录下,防止被编译
总结:
差异化编译需要注意:
1.差异化目录是否是独立的没有被其他编译包含
2.对应的源码,资源,libs,AndroidManifest.xml,是否修改到了并在build.gradle里面差异化配置
3.新增的功能是否会影响原有功能
4.新增差异化一定写上注释