Skip to content

Isolate routing change listeners for API 23 and API 24 in AudioTrack - #2

Merged
nift4 merged 1 commit into
nift4:gramophonefrom
SteveZMTstudios:gramophone
Aug 23, 2026
Merged

Isolate routing change listeners for API 23 and API 24 in AudioTrack#2
nift4 merged 1 commit into
nift4:gramophonefrom
SteveZMTstudios:gramophone

Conversation

@SteveZMTstudios

Copy link
Copy Markdown

This description was translated by Google.

Summary

We have prepared a class loading isolation fix to address an issue where AudioTrackAudioOutput throws a NoClassDefFoundError due to the lack of the AudioRouting interface in Android 6.0 (SDK level 23).

Details

Gramophone crashed on Android 6.0 and higher when testing compatibility and robustness at FoedusProgramme/Gramophone#1003.

Gramophone version: 1.1.2.2d6a2a8 (org.akanework.gramophone)

Release type: SelfBuilt
Brand: Android
Model: Android SDK built for x86_64
SDK Level: 23
Thread: ExoPlayer:Playback


Time: 2026-08-23 22:19:31
---------beginning of crash
java.lang.NoClassDefFoundError: androidx.media3.exoplayer.audio.AudioTrackAudioOutput$OnRoutingChangedListener$$ExternalSyntheticLambda2
at androidx.media3.exoplayer.audio.AudioTrackAudioOutput$OnRoutingChangedListener$$ExternalSyntheticLambda3.onRoutingChanged(r8-map-id-9f17be822be4a3f79def5490dd0489634150cfec786915dc286be0c2c2733cb8:5)
at android.media.AudioTrack$NativeRoutingEventHandlerDelegate$1.handleMessage(AudioTrack.java:2460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at `android.os.HandlerThread.run(HandlerThread.java:61)`

android.media.AudioRouting is a class introduced in Android 7.0 (API 24), and it doesn't exist in the framework of Android 6.0 (API 23, SDK Level 23). When a routing change event occurs on an API 23 device, the lambda generated inside this class is executed. ART throws a java.lang.NoClassDefFoundError because it cannot find the AudioRouting type when loading/validating the class members associated with this lambda.

On July 24, 2026, c9501075 introduced a new compatibility layer, re-based the media3 submodule on upstream code containing the new audio architecture (NativeTrack / AudioOutputProvider).

During this re-based upstream code process, commit 73c8dcd ("Added route change listeners to API 23 as well") was made. However, when modifying AudioTrackAudioOutput.java, the AudioRouting interface of API 24 and the listening logic of API 23 were written in the same inner class, causing the class loader to throw a NoClassDefFoundError error on Android 6.0 devices due to the lack of AudioRouting. Therefore, I made the following changes:

In media3 AudioTrackAudioOutput.java, a unified private interface OnRoutingChangedListener was defined, and a release() method was declared.

The original single implementation class, which mixed API 23 and API 24, was split into two independent implementation classes:

@RequiresApi(23) private static final class OnRoutingChangedListenerApi23: Only references android.media.AudioTrack.OnRoutingChangedListener, which exists in API 23, and no longer references any higher-version types.

@RequiresApi(24) private static final class OnRoutingChangedListenerApi24: References android.media.AudioRouting.OnRoutingChangedListener, which was introduced in API 24.

In the AudioTrackAudioOutput constructor, the corresponding listener implementation class is instantiated based on the SDK_INT branch condition:

If SDK_INT >= 24, then OnRoutingChangedListenerApi24 is instantiated.

If SDK_INT >= 23, then OnRoutingChangedListenerApi23 is instantiated.

If this value is lower than API 23, no route listener is created.

image

@nift4

nift4 commented Aug 23, 2026

Copy link
Copy Markdown
Owner

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants