如何在 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 Variants、libraryVariant
和 emptyVariant
,它们以编程方式通过 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"
}
我正在尝试在 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 Variants、libraryVariant
和 emptyVariant
,它们以编程方式通过 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"
}