Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Hugo and AndroidDevMetrics plugins compile only in debug:

I'm using Jack's Wharton Hugo Library and AndroidDevMetrics plugins to measure method execution time and application performance in Android. I need to make those libraries compile only in debug build and to exclude them from release builds.

Because both of those library applied only using the plugin syntax:

apply plugin: 'com.frogermcs.androiddevmetrics'
apply plugin: 'com.jakewharton.hugo'

and do not require any dependencies in the Gradle file I can't exclude them using the testCompile option. The only way supplied to control Hugo is setting this in the gradle file:

hugo {
   enabled false
}

while the only way to control AndroidDevMetrics is:

public class ExampleApplication extends Application {

@Override
 public void onCreate() {
     super.onCreate();
     //Use it only in debug builds
     if (BuildConfig.DEBUG) {
         AndroidDevMetrics.initWith(this);
     }
  }
 }

The question: Those control options do not prevent from those library files from being complied to the release version of the application. I'm looking for a way to exclude those plugins in Gradle in case I build a release version.

like image 749
Emil Adz Avatar asked May 26 '16 13:05

Emil Adz


1 Answers

You can use a combination of Proguard and Sourcesets to ensure that libraries aren't compiled into your release application, and gradle properties to apply plugins conditionally.

Conditionally including plugins

You can conditionally include a gradle plugin by declaring it as you normally would at the top of your build.gradle, and surrounding it with a conditional clause. For example, the code below checks whether a property exists, and if it does, applies the plugin.

if (hasProperty('shouldApplyDevMetrics')) {
    println "Applying devmetrics plugin"
    apply plugin: 'com.frogermcs.androiddevmetrics'
}
else {
    println "Not applying devmetrics plugin in release build"
}

To include a property, you can use the command line flag below when invoking gradle. You can create similar launch configurations if you wish to use Android Studio.

./gradlew assembleDebug -PshouldApplyDevMetrics=true

This removes the gradle plugin from the release build, but depending on the library, may leave compiled code in your app. You can address this using one of the two methods detailed below.

Using Proguard

The first (and simplest) approach to completely removing a library from an APK is to strip out all the relevant code using the Proguard tool. You should update your release buildType to enable proguard, and load a custom rules file.

release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

By default, this should strip out the annotations. It's possible that you will need to update your proguard configuration for other dependencies which rely on reflection or annotations. If enabling proguard produces compiler warnings relating to Hugo, you can disable them by adding the following line:

-dontwarn hugo.weaving**

This approach does mean that you need to keep the dependency in your build.gradle file, but is the best approach for something like Hugo, which is used all over the place by adding annotations.

Using Sourcesets

To remove the AndroidDevMetrics library from the release build entirely, we should start off by creating a debug and release sourceset, then add a functional class under src/debug, and a no-op class under src/release.

// src/debug
public class DevMetricWrapper() {
    void doMetricsThings(Context context) {
        AndroidDevMetrics.initWith(context);
    }
}

// src/release
public class DevMetricWrapper() {
    void doMetricsThings(Context context) {
        // no-op
    }
}

You can then alter the build.gradle file for your module so that the library is only included as a debug dependency:

debugCompile 'com.example.yourlibrary'

Please note that if you're planning on doing anything more complicated, Dagger is a very useful library as it allows you to inject different dependencies depending on what flavor you are building.

like image 171
fractalwrench Avatar answered Oct 21 '22 01:10

fractalwrench