How to configure gradle to use logback-classic ONL

2020-06-13 05:56发布

I have an Android app thich uses slf4j + logback. Gradle file looks like this:

...
compile('com.github.tony19:logback-android-core:1.1.1-6') {
    exclude group: 'ch.qos.logback.core.net'
}

compile('com.github.tony19:logback-android-classic:1.1.1-6') {
    exclude group: 'ch.qos.logback.core.net'
}

compile 'org.slf4j:slf4j-api:1.7.25'

And I have logback.xml in assets/. When I run the app logging work as expected. Recently I've decided to add new unit tests (regular, not android unit tests) but I saw that log messages are not shown.

I've added following to the gragle file:

testCompile('ch.qos.logback:logback-classic:1.2.3') {
    exclude group: 'com.github.tony19'
}

and now log messages are shown but on each run of the unit tests I get this warning:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/o/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/7c4f3c474fb2c041d8028740440937705ebb473a/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/o/.gradle/caches/modules-2/files-2.1/com.github.tony19/logback-android-classic/1.1.1-6/614c66c9ece69eef48c65a8558de4fd7266d9f69/logback-android-classic-1.1.1-6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

Is there a way to specify exclusively which slf4j binding to be used for the regular app runs and which for unit tests only (or any other solution)?

Dependencies graph:

compile - Classpath for compiling the main sources.
+--- com.bolyartech.forge.android:forge-android:7.1.0
|    +--- com.bolyartech.forge:base:5.1.0
|    |    +--- org.slf4j:slf4j-api:1.7.7 -> 1.7.25
|    |    +--- com.darwinsys:hirondelle-date4j:1.5.1
|    |    +--- com.google.guava:guava:20.0
|    |    +--- javax.inject:javax.inject:1
|    |    \--- com.squareup.okhttp3:okhttp:3.1.2
|    |         \--- com.squareup.okio:okio:1.6.0
|    +--- com.google.dagger:dagger:2.9
|    |    \--- javax.inject:javax.inject:1
|    +--- com.android.support:support-annotations:25.3.1 -> 26.0.1
|    +--- javax.annotation:jsr250-api:1.0
|    +--- com.android.support.test.espresso:espresso-idling-resource:2.2.2
|    \--- net.sourceforge.streamsupport:streamsupport:1.5.1
+--- com.bolyartech.scram_sasl:scram_sasl:2.0.1
+--- com.android.support:multidex:1.0.1
+--- com.squareup:otto:1.3.8
+--- com.google.code.gson:gson:2.7
+--- com.github.franmontiel:PersistentCookieJar:v0.9.3
|    \--- com.squareup.okhttp3:okhttp:3.1.2 (*)
+--- com.github.tony19:logback-android-core:1.1.1-6
+--- com.github.tony19:logback-android-classic:1.1.1-6
|    +--- com.github.tony19:logback-android-core:1.1.1-6
|    \--- com.github.tony19:apktool-lib:1.4.4-3
|         \--- com.google.android:android:2.1_r1
|              +--- commons-logging:commons-logging:1.1.1
|              +--- org.apache.httpcomponents:httpclient:4.0.1
|              |    +--- org.apache.httpcomponents:httpcore:4.0.1
|              |    +--- commons-logging:commons-logging:1.1.1
|              |    \--- commons-codec:commons-codec:1.3
|              +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|              +--- xerces:xmlParserAPIs:2.6.2
|              \--- xpp3:xpp3:1.1.4c
+--- ch.acra:acra:4.7.0
|    \--- com.android.support:support-v4:23.0.1 -> 26.0.1
|         +--- com.android.support:support-compat:26.0.1
|         |    \--- com.android.support:support-annotations:26.0.1
|         +--- com.android.support:support-media-compat:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         +--- com.android.support:support-core-utils:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         +--- com.android.support:support-core-ui:26.0.1
|         |    +--- com.android.support:support-annotations:26.0.1
|         |    \--- com.android.support:support-compat:26.0.1 (*)
|         \--- com.android.support:support-fragment:26.0.1
|              +--- com.android.support:support-compat:26.0.1 (*)
|              +--- com.android.support:support-core-ui:26.0.1 (*)
|              \--- com.android.support:support-core-utils:26.0.1 (*)
+--- org.slf4j:slf4j-api:1.7.25
+--- javax.inject:javax.inject:1
+--- javax.annotation:jsr250-api:1.0
+--- com.google.dagger:dagger:2.9 (*)
\--- com.android.support:appcompat-v7:26.0.1
     +--- com.android.support:support-annotations:26.0.1
     +--- com.android.support:support-v4:26.0.1 (*)
     +--- com.android.support:support-vector-drawable:26.0.1
     |    +--- com.android.support:support-annotations:26.0.1
     |    \--- com.android.support:support-compat:26.0.1 (*)
     \--- com.android.support:animated-vector-drawable:26.0.1
          +--- com.android.support:support-vector-drawable:26.0.1 (*)
          \--- com.android.support:support-core-ui:26.0.1 (*)


testCompile - Classpath for compiling the test sources.
+--- ch.qos.logback:logback-classic:1.2.3
|    +--- ch.qos.logback:logback-core:1.2.3
|    \--- org.slf4j:slf4j-api:1.7.25
+--- junit:junit:4.12
|    \--- org.hamcrest:hamcrest-core:1.3
\--- org.mockito:mockito-core:1.10.19
     +--- org.hamcrest:hamcrest-core:1.1 -> 1.3
     \--- org.objenesis:objenesis:2.1

3条回答
孤傲高冷的网名
2楼-- · 2020-06-13 06:26

With Android Gradle Plugin 3 and above, try to use following:

implementation 'org.slf4j:slf4j-api:1.7.25'   
runtimeOnly 'com.github.tony19:logback-android-core:1.1.1-6'
查看更多
淡お忘
3楼-- · 2020-06-13 06:27

Dependency Scope

In the old version of gradle, the dependency scope of compile will be included in all classpaths of projects, i.e. including compilation, runtime, test compilation and test execution. So the two implementations of SLF4J class will be included in test execution.

SLF4J Binding

And because the implementation of SLF4J bindings, two bindings will causes an warning, SLF4J will randomly choose a binding, in this case, not logback.

Solution

So, the only way to solve the problem is to exclude logback-android from your test classpath.

In the new version of Gradle (4.0.2), we define logback-android in runtimeElements to avoid be used by test environment. In old version, it seems that we cann't solve this problem with gradle.

Ref

查看更多
Juvenile、少年°
4楼-- · 2020-06-13 06:35

You need to exclude it on the root level, instead of the logback classic dependency:

configurations {
    testCompile.exclude group: 'com.github.tony19'
}
查看更多
登录 后发表回答