如何使AAR工件等效于'compileOnly'? [英] How to make an equivalent of 'compileOnly' for AAR artifacts?

查看:545
本文介绍了如何使AAR工件等效于'compileOnly'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在现实世界中,如果您正在为android项目编写ui测试,则在从Android Studio中按运行"后,它将组装两个应用程序:"your.cool.app"和"your.cool.app.test" .测试应用将在android中显示类似以下内容:

In real world, if you're writing ui tests for android project, after press 'Run' from Android Studio, it will assemble two apps: 'your.cool.app' and 'your.cool.app.test'. Test app will have in android manifest something like:

<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                 android:targetPackage="your.cool.app"/>

这实际上意味着,如果同时安装它们和您的测试应用程序,则它们将与真正的应用程序合并-所有依赖项(第三方库等)都将在一个运行时类路径中.因此,如果两个应用程序将具有某种类型的库,则它们将无法合并,因为不可能在运行时类路径中过多地包含多个类,您将得到一个重复类异常.

Which actually will be mean, that if you install them both, your test app will be merged with a real one - all dependencies (third-party libs etc..) will be in one runtime classpath. So if two apps will have some sort of libraries, they can't be merged, since it's impossible to have more than one class in runtime classpath overwise you will get a duplicated classes exception.

这就是为什么您拥有Android插件功能的原因,该功能允许您为测试应用程序-androidTestImplementation添加依赖项.因此,如果您添加两个类似的依赖项,例如:

That's why you have a functionality of Android Plugin which allows you to add dependencies for test app - androidTestImplementation. So if you add two similar dependencies like:

implementation 'com.google.android.material:material:1.0.0'
androidTestImplementation 'com.google.android.material:material:1.0.0'

Gradle将解决此类问题.因此,对于实际应用程序,它将添加到 compile runtime 类路径中;对于测试应用程序,它将仅添加用于 compile 类路径(这就是为什么可以导入的原因测试类中所有来自依赖项的东西)

Gradle will resolve this kind of issue. So for real app it will add to compile and runtime classpaths and for test app it will add only for compile classpath (that's why you can import all stuff from dependency in test classes)

出于某种原因,我正在使用两个不同的应用程序.当我为这两个应用程序添加依赖项时:

For some reason i'm working with two different apps. And when i'm adding a dependency for these two apps like:

implementation 'com.google.android.material:material:1.0.0'

我将有一个Duplicate classes '...'

是的,最好的解决方案是制作一个单声道仓库,然后让Android Gradle插件解决此问题... 但是我不能,因为在这种情况下,没有主代码就无法共享测试代码.

Yes, the best solution is to make a mono repo, and let Android Gradle Plugin resolve this... But i can't, since in this situation you can't share your test code, without main code.

是的,我们已经有一个'compileOnly',它可以完美地工作(它只添加了对编译类路径的依赖),但是它仅适用于 JAR .因此,我需要一个像'compileOnly'这样的工件配置,但要使用 AAR

Yes, we already have an 'compileOnly' which works perfectly (it's only add a dependency to compile classpath) but it only works for JARs. So i need an artifact configuration like 'compileOnly' but for AARs

我已经尝试过的:

allprojects {
    createCompileOnlyAarConfiguration(project)
}

def createCompileOnlyAarConfiguration(Project project) {

    def compileOnlyAarConf = project.configurations.create('compileOnlyAar')
    compileOnlyAarConf.visible = false
    compileOnlyAarConf.transitive = false

    project.gradle.addListener(new DependencyResolutionListener() {
        @Override
        void beforeResolve(ResolvableDependencies resolvableDependencies) {
            compileOnlyAarConf.dependencies.each { dependency ->
                project.dependencies.add('compileOnly', dependency)
            }
            project.gradle.removeListener(this)
        }

        @Override
        void afterResolve(ResolvableDependencies resolvableDependencies) {
        }
    })
}

现在我可以做类似的事情了:

So now i can make something like:

dependencies {
    compileOnlyAar 'com.google.android.material:material:1.0.0'
}

通过这种配置,我可以使用这些依赖关系中的所有类,但是在最终的dex文件中,其中没有使用过的方法的引用.这就是为什么我得到java.lang.NoSuchMethodError: java.lang.NoSuchMethodError: No static method

And with this configuration i can use all classes from these dependency but in final dex file where is no reference for methods that i've used. That's why i get java.lang.NoSuchMethodError: java.lang.NoSuchMethodError: No static method

我还找到了一个渐变插件,它实际上添加了一个'compileOnlyAar'配置,但是它仅适用于Java模块

I also found a gradle plugin, which actually adds a 'compileOnlyAar' configuration, but it works only with java module

我在gradle环境中表现不佳,因此,如果有人可以指出我如何为AAR工件制作"compileOnly",那就太酷了.

I'm not that good in gradle enviroment, so it would be cool if someone can point me how to make 'compileOnly' for AAR artifacts.

更新: 出于某种原因,我正在使用两个不同的应用程序"-意味着我也具有"your.cool.app"和"your.cool.app.test"应用程序.但是它们具有自己的gradle依赖关系,并且测试应用在AndroidManifest中具有instrumentation属性. 'your.cool.app'-主代码库,'your.cool.app.test'-所有ui测试.安装完两者后,我只是通过adb shell am instrument运行测试.测试应用程序和主应用程序需要依赖com.google.android.material:material:1.0.0,因此它们都包含:

UPDATE: "For some reason i'm working with two different apps" - means, that i have 'your.cool.app' and 'your.cool.app.test' apps aswell. But they have own gradle dependencies and test app have instrumentation attribute in AndroidManifest. 'your.cool.app' - main codebase, 'your.cool.app.test' - all ui tests. After installing both i just run tests via adb shell am instrument. Test app and main app need dependency com.google.android.material:material:1.0.0 so both of them contains:

dependencies {
   implementation 'com.google.android.material:material:1.0.0'
}

因此,正如我所说,如果我安装两个应用程序并通过adb shell am instrument开始测试,我将得到重复的类异常,因为两个二进制文件在运行时类路径中都将是两次.

So as i said, if i install both apps and start test via adb shell am instrument, i will get duplicated class exception, since both binaries will be twice in runtime classpath.

为什么我需要这种结构?没有主代码库,我只能共享测试应用程序.因此,我无法制作标准的monorepo

Why i need this structure? I can share only test app without main codebase. So there is no way to me to make a standard monorepo

推荐答案

在android studio的右侧,转到gole gradle>您的libraryapp>运行配置>组装.AAR将出现在您所选项目的输出文件夹中

On the Right side of android studios goto gradle>your libraryapp>Run configurations>asssemble .AAR will be present in outputs folder of your selected project

这篇关于如何使AAR工件等效于'compileOnly'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆