From 0de938c4aa61c76c2fbc75b3040aa11669fb3388 Mon Sep 17 00:00:00 2001 From: krocard Date: Thu, 15 Oct 2020 08:12:32 +0100 Subject: [PATCH] Do not inherit directly from AudioTrack.StreamEventCallback This was causing issues old devices where the class inheriting StreamEventCallback was loaded even though it was not used. Instead use an anonymous class that seem to be loaded more lazily. PiperOrigin-RevId: 337252687 --- RELEASENOTES.md | 3 ++ .../exoplayer2/audio/DefaultAudioSink.java | 46 +++++++++++-------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1b2c273cd2..fbc0238a35 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -32,6 +32,9 @@ * Fix the default audio sink position not advancing correctly when using `AudioTrack`-based speed adjustment ([#7982](https://github.com/google/ExoPlayer/issues/7982)). + * Fix `NoClassDefFoundError` warning for `AudioTrack$StreamEventCallback` + even though the class was not used + ([#8058](https://github.com/google/ExoPlayer/issues/8058)). * Extractors: * Add support for .mp2 boxes in the `AtomParsers` ([#7967](https://github.com/google/ExoPlayer/issues/7967)). diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index 478eb0d04b..2ebd744812 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -1696,37 +1696,43 @@ public final class DefaultAudioSink implements AudioSink { } @RequiresApi(29) - private final class StreamEventCallbackV29 extends AudioTrack.StreamEventCallback { + private final class StreamEventCallbackV29 { private final Handler handler; + private final AudioTrack.StreamEventCallback callback; public StreamEventCallbackV29() { handler = new Handler(); - } + // StreamEventCallbackV29 can NOT inherit directly from AudioTrack.StreamEventCallback as it + // would cause a NoClassDefFoundError on the first load of DefaultAudioSink for SDK < 29 + // fatal on some devices. See: https://github.com/google/ExoPlayer/issues/8058 + callback = + new AudioTrack.StreamEventCallback() { + @Override + public void onDataRequest(AudioTrack track, int size) { + Assertions.checkState(track == DefaultAudioSink.this.audioTrack); + if (listener != null) { + listener.onOffloadBufferEmptying(); + } + } - @Override - public void onDataRequest(AudioTrack track, int size) { - Assertions.checkState(track == DefaultAudioSink.this.audioTrack); - if (listener != null) { - listener.onOffloadBufferEmptying(); - } - } - - @Override - public void onTearDown(@NonNull AudioTrack track) { - if (listener != null && playing) { - // A new Audio Track needs to be created and it's buffer filled, which will be done on the - // next handleBuffer call. - // Request this call explicitly in case ExoPlayer is sleeping waiting for a data request. - listener.onOffloadBufferEmptying(); - } + @Override + public void onTearDown(@NonNull AudioTrack track) { + if (listener != null && playing) { + // A new Audio Track needs to be created and it's buffer filled, which will be done + // on the next handleBuffer call. Request this call explicitly in case ExoPlayer is + // sleeping waiting for a data request. + listener.onOffloadBufferEmptying(); + } + } + }; } public void register(AudioTrack audioTrack) { - audioTrack.registerStreamEventCallback(handler::post, this); + audioTrack.registerStreamEventCallback(handler::post, callback); } public void unregister(AudioTrack audioTrack) { - audioTrack.unregisterStreamEventCallback(this); + audioTrack.unregisterStreamEventCallback(callback); handler.removeCallbacksAndMessages(/* token= */ null); } }