Search code examples
javaandroidgradlebuildbuild-time

Turn off parts of code to speed up build times (Gradle)


I have an Android project that has grown with time, and with the size have grown the gradle build times.

It was bearable while it was under the 65k limit - around 14s. Now with multidex it takes 36s.

So my question is - are there any ways to "turn off" parts of the code that are not being used so it's back under the 65k limit?

For e.g. turn off the amazon s3 sdk which is brought in via gradle and has n thousands of methods.

I know you can strip code with proguard, but that just bumps up the build time even higher.

I'm happy with it crashing at runtime when I open the parts that use it, just want to make testing quicker.

At the moment when I remove amazon from gradle imports, I obviously get this: Error:(24, 26) error: package com.amazonaws.auth does not exist

Is there a way to somehow ignore the error? I know that in Picasso, it has a runtime check to see if you have OkHttp, and if you haven't - use standard networking.

static Downloader createDefaultDownloader(Context context) {
    if (SDK_INT >= GINGERBREAD) {
       try {
         Class.forName("com.squareup.okhttp.OkHttpClient");
         return OkHttpLoaderCreator.create(context);
       } catch (ClassNotFoundException ignored) {}
    }
    return new UrlConnectionDownloader(context);
}

Is there something like this I could do? Or any other way?


Solution

  • It is possible to specify compile-time dependencies for each build type independently. I use this method to include "production-only" dependencies in only the release builds, reducing the method count for debug builds.

    For example, I only include Crashlytics in release builds. So in build.gradle I include the dependency for only my release build (and beta and alpha):

    releaseCompile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
        transitive = true;
    }
    

    Then I abstract the functionality of Crashlytics into a class called CrashReportingService. In my debug source code, this class does nothing:

    /app/src/debug/java/com/example/services/CrashReportingService.java:

    public class CrashReportingService {
        public static void initialise(Context context) {
        }
    
        public static void logException(Throwable throwable) {
        }
    }
    

    And I flesh out the implementation in my release source code:

    /app/src/release/java/com/example/services/CrashReportingService.java

    public class CrashReportingService {
        public static void initialise(Context context) {
            Fabric.with(context, new Crashlytics());
        }
    
        public static void logException(Throwable throwable) {
            Crashlytics.getInstance().core.logException(throwable);
        }
    }
    

    Crashlytics is now only included in release builds and there is no reference to Crashlytics in my debug builds. Back under 65k methods, hooray!