简体   繁体   中英

How to make an equivalent of 'compileOnly' for AAR artifacts?

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 .

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 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'

I will have a Duplicate classes '...'

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.

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

What i've already tried:

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'
}

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

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

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.

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'
}

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.

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 studios 的右侧,转到 gradle>your libraryapp>Runconfiguration>asssemble .AAR 将出现在您选择的项目的输出文件夹中

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM