为编译和运行时选择不同的库

时间:2016-11-25 19:06:07

标签: android-studio gradle android-gradle static-libraries aar

我有两个库,每个库都定义了相同的类。但是它们有一些不同的内容(方法/常量)。

例如:

图书馆1:

package com.test.package;
Class A {
     // only method signatures
     public void methodA() {
     }

     public void methodB() {
     }
}

图书馆2:

package com.test.package;
Class A {  
     public void methodA() {
          // some logic that MUST be executed to provide backward compatibility
     }
}

我的应用程序使用库1和库2,并在具有com.test.package.ClassA的设备中运行,但com.test.package.ClassA.methodB()仅存在于框架中的较新版本中。说,我需要使用库1来编译我的应用程序,并使用库2来执行methodA()的不同实现。

我尝试使用.jar和.aar库格式在Android Studio中执行此操作,但这些都不适用于我。

是否可以在Android Studio项目中设置此配置?

我正在构建库1和库2,我无法在库2中添加methodB()。

1 个答案:

答案 0 :(得分:0)

对于简单的Java应用程序,您可以通过取消链接compileruntime配置来执行此操作。我设置了一个示例存储库here

这个想法显示在this commit中,但可以描述为手动重置runtime配置,使其不包含compile配置的内容。完成此操作后,您可以在runtime配置中包含运行时库变体。

应用程序的build.gradle变成了:

apply plugin: 'application'

mainClassName = 'my.package.MyAppClass'

configurations.runtime.extendsFrom = [] // Reset runtime configuration

dependencies {
    compile 'my.group:my.artifact:2.0'  // Library 1, with the new method
    runtime 'my.group:my.artifact:1.0'  // Library 2, without the method
}

对于Android,这可能会有点复杂。问题是Android没有runtime配置(因为你没有在你的计算机上执行它,除非你使用Robolectric或类似的东西)。

我认为你可以使用一些解决方法,但最初的建议是创建一个包装库来抽象出对其他库的依赖。这个包装器库可以使用最新的库版本(库1,使用新方法)进行编译。然后,您可以在Android应用程序中包含包装器库,同时将其设置为非传递依赖项并包括其他库版本:

dependencies {
    compile 'my.group:my.wrapped.artifact:0.1' {
        transitive = false  // Don't include dependencies of the wrapper
                            // i.e., don't include version 2.0 of the lib.
    }
    compile 'my.group:my.artifact:1.0'
}

这应该有效,因为通过将依赖项设置为非传递性Gradle不会递归地包含包装器库的依赖项,因此用于编译包装器的版本不会(在理论上)包含在APK中。因此,您可以在不引起冲突的情况下添加旧版本。

Android branch下的同一个存储库中设置了一个示例。首先,创建两个Java库。然后an Android library is created包围编译时库。一个example activity is created来显示使用包装器库如何使用编译时库。然后,latest commit显示应用程序如何配置为使用包装器库(使用最新的库编译),但强制将旧库包含在运行时中。

希望这有助于=)