如何在 Android 中有条件地编译 JAR?

How to conditionally compile a JAR in Android?

我正在尝试在 Android Studio 中进行条件构建,如果特定发行版不需要它们,我可以通过删除任何多余的库依赖项来减小生成的 APK 的大小。

我有一些代码大致如下:

public class MyClass {

    /* Static Declarations. */
    public static final boolean USE_LIBRARY = false;

    public void doSomething() {
        // Are we using the library?    
        if(MyClass.USE_LIBRARY) {
            // Do something with the library that we'd define in my build.gradle.
            com.some.gradle.library.MyLibrary.doSomethingWithLibrary();
        }
        else {
            // Do something else.
        }
    }

}

如果我从我的 Gradle 依赖项中删除 com.some.gradle.library,我会收到编译错误,表明无法编译上述代码。如您所见,只要 USE_LIBRARY 保持为假,我们就永远不需要引用 MyLibrary;甚至在实例化时也没有,因为它没有引用导入;这些仅在运行时被侵犯。

我可能应该注意到,在实践中,USE_LIBRARY 是以编程方式生成的与应用程序的 BuildConfig.java.

有关的常量

难道编译器可以判断这段代码可以优化吗?这是我可以解决的某种预处理器检查吗?

I'm trying to make a conditional build in Android Studio, where I can reduce the size of the generated APK by removing any superfluous library dependencies if they're not needed for a particular distribution.

第 1 步:为 "particular distribution" 定义产品口味。出于此答案的目的,我将其称为 foo。您还需要其他发行版的其他产品口味。

第 2 步:将拉入此 JAR 的 compile 语句更改为 fooCompile 语句,因此它将仅用于 foo 构建。

第 3 步:在每个产品风味的源集中(例如,src/foo/java/)都有一个 MyClass 版本,其中 foo 中的版本引用库,而其他人则没有。

我认为您可能混淆了 Java 运行时和编译时进程的行为。

在运行时,您的代码可以有条件地执行并且可以忽略库调用,但在编译时处理所有代码。

通过编译时引用库,编译时需要依赖

但是,有一个名为 Proguard 的实用程序是 android 构建系统的一部分,它可以从 apk 中删除未使用的字节代码。另外,检查@CommonsWare 的回答,如果您根本没有在不同版本中使用该库,那么构建类型允许您在没有该库的情况下创建一个单独的 apk 版本

找到解决方案。我采用的上述方法 可能的,前提是您可以保证在运行时不会与任何库代码进行交互;这包括确保 none 的运行时 类 extend 任何 parents 或 implement 接口是库的一部分。我能够使用 ClassyShark.

验证代码是否已被删除

"trick" 是将库组件声明为 provided 用于您想要假装 库可供您使用的构建变体,并且作为 compile 当您希望导出库时。

即使用两个 Build VariantslibraryVariantemptyVariant,它们以编程方式通过 buildConfigField 'boolean', 'USE_LIBRARY', 'X' 切换 USE_LIBRARY 的值。然后你可以定义你的依赖如下:

dependencies {
    // Actually package the library with the compiled APK.
    libraryVariantCompile  "com.some.gradle.library:-1"
    // Ignore the library; just please the linting process.
    emptyVariantProvided   "com.some.gradle.library:-1"
}