I have a SampleApp with a library module attached:
:app
:library
The library is using the following dependency and the following code:
implementation "com.google.android.gms:play-services-safetynet:17.0.1"
----
import android.content.Context
import com.google.android.gms.safetynet.SafetyNet
class ClassUsingSafetynet {
fun trigger(context: Context) {
SafetyNet.getClient(context)
}
}
The SampleApp is calling trigger
somewhere:
val triggerClass = ClassUsingSafetynet()
triggerClass.trigger(context)
This works without problems as long as the SampleApp declares its dependency directly on the library module:
implementation project(path: ':library')
But if I deploy the library aar to my local maven and declare the dependency accordingly like this:
implementation ('com.myapplication:library:1.0.3@aar') { transitive = true }
I get the following crash
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/safetynet/SafetyNet;
at com.library.ClassUsingSafetynet.trigger(ClassUsingSafetynet.kt:10)
at com.myapplication.MainActivity.onCreate$lambda-0(MainActivity.kt:38)
Here is the publish gradle task:
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
groupId 'com.myapplication'
artifactId 'library'
version '1.0.3'
artifact 'build/outputs/aar/library-release.aar'
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.api.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
repositories {
mavenLocal()
}
}
}
I have tried to use api
instead of implementation
for the SafetyNet dependency. No difference.
I have tried to set/not set {transitive = true}
. No difference.
I have tried to set/not set @aar
. No difference.
I have tried to not create the pom file. No difference.
No ProGuard is applied for now.
What's especially strange to me is that "SafetyNet" is a private dependency of the library. My app doesn't even need to know about it.
CodePudding user response:
The published POM file needs to declare all runtime dependencies of the library, not just its API dependencies. In other words, you need to use the following when adding dependencies to the POM:
configurations.releaseRuntimeClasspath.allDependencies.each {
// …
}
The following is a misunderstanding:
"SafetyNet" is a private dependency of the library. My app doesn't even need to know about it.
Your app should indeed not have to worry about this “private dependency” but it still has to (be able to) make it available to the library at runtime – as the library doesn’t work without it because it still is a dependency of the library.
I’ve successfully tested this change with a small dummy Android project. Let me know if you can’t get your build to work with the above information; then I can add a self-contained, working sample project to my answer.
That said, I wonder why you manually (a) specify the published artifact and (b) create the POM? The following should work automagically (tested as described above):
release(MavenPublication) {
groupId 'com.myapplication'
artifactId 'library'
version '1.0.3'
from components.release
}
See also the docs.