【问题标题】:How to conditionally compile a JAR in Android?如何在 Android 中有条件地编译 JAR?
【发布时间】:2017-10-06 18:40:03
【问题描述】:

我正在尝试在 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 相关的以编程方式生成的常量。

编译器肯定可以确定这段代码可以优化吗?这是我可以解决的某种预处理器检查吗?

【问题讨论】:

    标签: android gradle build compilation lint


    【解决方案1】:

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

    第 1 步:为“特定分布”定义产品风味。出于此答案的目的,我将其称为foo。对于其他发行版,您还需要其他产品风味。

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

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

    【讨论】:

    • 这听起来很有希望。我有第一阶段和第二阶段,但我不知道第三阶段甚至是一个选项!我会告诉你我过得怎么样,谢谢。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 感谢您的澄清。麻烦的是,连proguard 似乎都无法消除这个库!
    【解决方案3】:

    找到了解决办法。我采取的上述方法可能的,前提是您可以保证在运行时不会与任何库代码进行交互;这包括确保您的运行时类extend 没有任何父级或implement 接口是库的一部分。我能够使用ClassyShark 验证代码已被删除。

    “诀窍”是将库组件声明为provided 用于您想要假装库可供您使用的构建变体,并声明为compile 用于您希望导出库。

    即使用两个构建变体libraryVariantemptyVariant,它们以编程方式通过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"
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-07
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 2020-02-06
      • 2013-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多