I have a library that uses Kotlin Coroutines and uses the CoroutineScope as
private val coroutineScope by lazy(mode = LazyThreadSafetyMode.NONE) {
CoroutineScope(Dispatchers.Main)
}
When I use the library in other projects I am getting error:
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.ClassNotFoundException: Didn't find class "kotlinx.coroutines.Dispatchers" on path: DexPathList[[zip file "/data/app/com.ssss.ssss-X44QPiLhKdl-D6eyVAYkOA==/base.apk"],nativeLibraryDirectories=[/data/app/com.ssss.testauthenticater-X44QPiLhKdl-D6eyVAYkOA==/lib/x86, /system/lib, /system/product/lib]]
I have added -keepnames class kotlinx.** { *; }
in my consumer pro guard file as well.
Does anyone have similar issue? I am using coroutine 1.3.3 in android.
Can you please use this version and try again:
kotlin_coroutinesVersion = "1.2.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutinesVersion"
ClassNotFoundException can appears due to wrong generation of pox.xml file, which contains dependencies graph of the library, here is a script for publishing library to local maven repo and generating pom.xml file:
https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017
For applying it to library need to add publishMavenLocal.gradle to library project and put this line at the bottom of library build.gradle: apply from: 'publishMavenLocal.gradle'.
Also for testing it from local maven repo there should be additional identificator in test app gradle file - transitive = true, like this:
implementation ('com.example.android:library:0.0.1-library#aar') { transitive = true }
After sometime with help of link posted by #orest-herdil above, I figured out the issue was the dependency of my library module were not added in the POM file generated while bundling the AAR file. So I updated my maven publish code as:
publishing {
publications {
aar(MavenPublication) {
groupId "com.mylibrary"
version "1.1.1"
artifactId "awesome"
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each { dependency ->
final dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
}
The part pom.withXml { .... } will go through all the dependency in my library module and add them in generating POM file one by one. As of now the compile is already deprecated, I am going through implementation dependency only.
Related
I've just migrated my Android lib from JCenter to MavenCentral. The process completed successfully and I can find my lib through Sonatype Repo Search.
However, when I try to use the lib in my sample application, I get the following error:
Execution failed for task ':sample:checkDebugAarMetadata'.
> Could not resolve all files for configuration ':sample:debugRuntimeClasspath'.
> Could not find :unspecified:.
Required by:
project :sample > com.techyourchance:threadposter:1.0.0
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
It looks like Gradle finds my lib (because if I change to a non-existent version, say 2.0.0, then I get completely different error), but there is some problem with the artifact.
All the source code (both the lib and the sample app) can be found here. Specifically, here is build.gradle of the lib and that's the additional Gradle script that handles publication to Sonatype.
I've already spent two hours searching for each of the above error messages on the internet, but couldn't solve this issue so far.
Skip dependencies with name 'unspecified' in your publish-maven.gradle.
withXml {
def dependenciesNode = asNode().appendNode('dependencies')
project.configurations.implementation.allDependencies.each {
if (it.name != 'unspecified') {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
I am using maven-publish plugin in gradle to publish artifacts. I need to generate a POM file that contains dependencies so that my consumers can fetch the needed dependencies.
Since maven-publish does not by default contains dependencies onto POM file, I had to use
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'compile')
}
}
It was all working fine to me until I swapped keyword compile to api or Implementation.
the published POM does not contain any dependencies uses keyword api or Implementation. I had to use compile to make it included in POM file, am I missing anything here?
After couple of hours searching online, I just realized that the property you include POM file is changed as well.
It now become
//for implementation dependencies
configurations.implementation.allDependencies.each { ... }
//for api dependencies
configurations.api.allDependencies.each { ... }
However,
configurations.implementation.allDependencies.each { ... }
seems includes api dependencies in the POM file already.
you can simply skip the scope part, you hardly come across maven dependencies with scopes. ':D
When I build an app with a *.aar file instead of the module with Gradle 4.x and following the docu concerning implements and api, I expect using api the included aar file has all dependencies included, but it hasn't.
When you do
git clone https://github.com/hannesa2/aar_dependency
./gradlew clean assembleDebug
means
dependencies {
api project(':mylibrary')
it works properly.
But when I use insted of lib-module the previous generated *.aar file as dependency
dependencies {
api 'com.example.my.mylibrary:mylibrary-debug#aar'
(in demo app just do)
git checkout with_aar
./gradlew clean assembleDebug
I run into this
Task :app:transformClassesWithDesugarForDebug
Exception in thread "main" java.lang.TypeNotPresentException: Type io.reactivex.ObservableTransformer not present
at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:85)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:63)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1067)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.visitInvokeDynamicInsn(LambdaDesugaring.java:399)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
Because I ordinary run into this with uploading the aar artifacts into our company Maven Nexus, I created this demo-repo to show exactly what's wrong. In demo app or using Maven I see the same issue.
Does someone knows what I did wrong ?
I was able to solve it. The main issue was Android O with Gradle 4.x using api
dependencies {
api 'com.squareup.okhttp3:logging-interceptor:3.4.1'
api "io.reactivex.rxjava2:rxandroid:$versions.libs.rxAndroid"
Most answers are concerning something like this
publishing {
publications {
mipartner(MavenPublication) {
groupId '...'
artifactId '..'
version 1.0
artifact "$buildDir/outputs/aar/myLib-release.aar"
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
repositories{
maven {
url "https://some.url.com"
}
}
}
but here in the resulting *.pom there are no dependencies included, after change this line to api the dependencies are included in deployed pom !
configurations.api.allDependencies.each { dependency ->
after this you can easily consume the aar file
dependencies {
api "com.mylib.net:mylib:1.0"
When I build an app with a *.aar file instead of the module with Gradle 4.x and following the docu concerning implements and api, I expect using api the included aar file has all dependencies included, but it hasn't.
When you do
git clone https://github.com/hannesa2/aar_dependency
./gradlew clean assembleDebug
means
dependencies {
api project(':mylibrary')
it works properly.
But when I use insted of lib-module the previous generated *.aar file as dependency
dependencies {
api 'com.example.my.mylibrary:mylibrary-debug#aar'
(in demo app just do)
git checkout with_aar
./gradlew clean assembleDebug
I run into this
Task :app:transformClassesWithDesugarForDebug
Exception in thread "main" java.lang.TypeNotPresentException: Type io.reactivex.ObservableTransformer not present
at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:85)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:63)
at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1067)
at com.google.devtools.build.android.desugar.LambdaDesugaring$InvokedynamicRewriter.visitInvokeDynamicInsn(LambdaDesugaring.java:399)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
at org.objectweb.asm.MethodVisitor.visitInvokeDynamicInsn(Unknown Source)
Because I ordinary run into this with uploading the aar artifacts into our company Maven Nexus, I created this demo-repo to show exactly what's wrong. In demo app or using Maven I see the same issue.
Does someone knows what I did wrong ?
I was able to solve it. The main issue was Android O with Gradle 4.x using api
dependencies {
api 'com.squareup.okhttp3:logging-interceptor:3.4.1'
api "io.reactivex.rxjava2:rxandroid:$versions.libs.rxAndroid"
Most answers are concerning something like this
publishing {
publications {
mipartner(MavenPublication) {
groupId '...'
artifactId '..'
version 1.0
artifact "$buildDir/outputs/aar/myLib-release.aar"
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
repositories{
maven {
url "https://some.url.com"
}
}
}
but here in the resulting *.pom there are no dependencies included, after change this line to api the dependencies are included in deployed pom !
configurations.api.allDependencies.each { dependency ->
after this you can easily consume the aar file
dependencies {
api "com.mylib.net:mylib:1.0"
Setup
I have an android project setup in such a way that: Main depends on Module A and Module A depends on Module B.
Both A and B are compiled to aar files and uploaded to local maven repository. And in Main project, the importing of Module A is explicit.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile(group: 'com.test', name: 'ModuleA', version: '0.0.1', changing: true)
}
Error
When running the Main project, it failed with NoClassDefFoundError at places where Module A uses Module B.
This error is gone once I explicitly import Module B into Main project.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile(group: 'com.test', name: 'ModuleA', version: '0.0.1', changing: true)
compile(group: 'com.test', name: 'ModuleB', version: '0.0.1', changing: true)
}
Question
Can't gradle resolve the dependencies automatically? Or do I have to include all Module A's dependencies in the build.gradle of Main project?
I think it is related to the pom file generation, in pom file you can define dependency section. How do we let gradle know to include the dependencies in generating the pom file?
Edit #1
The build.gradle for ModuleA is like the following:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile(group: 'com.test', name: 'ModuleB', version:'0.0.1', ext: 'aar', changing: true)
}
publishing {
publications {
aar(MavenPublication) {
groupId packageId
version = versionId
artifactId libraryId
artifact("$buildDir/outputs/aar/${project.getName()}-debug.aar")
}
}
}
artifactory {
contextUrl = "${artifactory_contextUrl}"
publish {
repository {
repoKey = 'libs-release-local'
maven = true
username = "admin"
password = "password"
}
defaults {
publications('aar')
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team': 'core']
publishPom = true
}
}
resolve {
repository {
repoKey = 'libs-release'
maven = true
}
}
}
What do you mean by "automatically"? If the dependency does not exist in a defined path with well-defined names in your gradle.build, it will not find it. What may be misleading is that references to libraries in repositories can include dependencies to other libraries. When gradle requests the library location, the server responds with a file that specifies the location and dependencies, if applicable.
An aar file does not include your gradle.build or another dependency file that gradle can use, so any dependencies defined in your Module A gradle.build are not available to your main gradle.build. So you can't expect gradle to go to the source location of your Module B because it isn't there.
I think libraries in repositories do not make this clear because if a library with dependencies is in a repo then those dependencies seem to "magically" be included when you do a build. This is because the library reference can include references to the other dependencies and gradle is given that information when it requests the library. The repo library entry/definition includes dependencies.
If this is the type of behavior you are looking for, you should put your aar in a repo (public or self-hosted) and then create an appropriate library definition in the repo (like a pom.xml file), specify the dependency and add the dependency library to the repo also.
EDIT:
Also gradle does not support parsing pom files natively. So you cannot directly reference a pom file to identify dependencies. However, it will work with repositories that identify dependencies (and those repositories can use pom files, but gradle does not parse them). See the docs here: https://docs.gradle.org/current/userguide/dependency_management.html
Also, see the related question about gradle's lack of support for parsing pom files: Reading info from existing pom.xml file using Gradle?
Finally find a solution for gradle to generate pom with dependencies, add the following to publishing task:
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.getByName("_releaseCompile").getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}