T. Barusseau
T. Barusseau

Reputation: 335

Is it possible to have two different versions of a same library coexist?

I'm developing a react-native application which plays both audio and video files. So I'm using two javascript dependencies: react-native-track-player and react-native-video.

Individually, they work fine. Together though...

07-23 09:41:24.052 24644 24644 E AndroidRuntime: FATAL EXCEPTION: main
07-23 09:41:24.052 24644 24644 E AndroidRuntime: Process: com.myapp, PID: 24644
07-23 09:41:24.052 24644 24644 E AndroidRuntime: java.lang.NoSuchMethodError: No virtual method setAudioAttributes(Lcom/google/android/exoplayer2/audio/AudioAttributes;)V in class Lcom/google/android/exoplayer2/SimpleExoPlayer; or its super classes (declaration of 'com.google.android.exoplayer2.SimpleExoPlayer' appears in /data/app/~~JZaWLKING3kOoM2Xhy3b8g==/com.myapp-ZiTzxTcb_NCKba7M-tUmIw==/base.apk!classes2.dex)

After some research, it seems to come from a version mismatch, as they both rely on exoplayer.

dependencies {
    implementation('com.google.android.exoplayer:exoplayer:2.13.2') {
        exclude group: 'com.android.support'
    }
}
def safeExtGet(prop, fallback) {
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

dependencies {
    def exoPlayerVersion = safeExtGet("exoPlayerVersion", '2.11.4')
    implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}"
}

react-native-track-player seems to fall back to 2.11.4: if I hard-code the version number instead of calling safeExtGet, I can observe the same crash.

The weird thing is that there are no errors (or warnings!) at build time. When looking at the react-native-track-player android code using Android Studio, setAudioAttributes is a valid method (at least no errors are reported by the IDE).

My questions are:

  1. Is it possible to have two different versions of a same library coexist, and have the Java code being properly linked to whichever version is used in the library? (in this case: exoplayer)
  2. If it is possible, could the behavior I'm observing come from some settings in these projects' build.gradle files?
  3. If it's not possible, what's the default behavior? "Keep the higher version silently"?

Thanks in advance.

Upvotes: 8

Views: 2230

Answers (1)

T. Barusseau
T. Barusseau

Reputation: 335

After discussing the issue with some people, it appears that it's impossible to have two different versions of a same library. It seems to be a limitation of the JVM, with Maven, Gradle, and Sbt all having different behaviors when confronted with the issue.

What most surprises me is that Gradle silently override the lower-version dependency with the higher one without notifying me, which results in a different runtime API, and thus crashes.

I fixed the issue by bumping my react-native-track-player exoplayer dependency version to 2.13.2, and just had to do minor changes in the source code.

Upvotes: 7

Related Questions