From fff2e0be7effe3b20576c1ff657871f7426b4eeb Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Wed, 12 Aug 2026 13:43:05 +0200 Subject: [PATCH 1/2] fix(android): declare edge-to-edge opt-in for SDK 35 and bump core-ktx to 1.16.0 Co-Authored-By: Claude Sonnet 4.6 --- Android/app/src/main/res/values-v35/themes.xml | 11 +++++++++++ Sources/Maxi80Services/Skip/skip.yml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Android/app/src/main/res/values-v35/themes.xml diff --git a/Android/app/src/main/res/values-v35/themes.xml b/Android/app/src/main/res/values-v35/themes.xml new file mode 100644 index 0000000..d70440b --- /dev/null +++ b/Android/app/src/main/res/values-v35/themes.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/Sources/Maxi80Services/Skip/skip.yml b/Sources/Maxi80Services/Skip/skip.yml index 8c0421f..e39c18a 100644 --- a/Sources/Maxi80Services/Skip/skip.yml +++ b/Sources/Maxi80Services/Skip/skip.yml @@ -11,5 +11,5 @@ build: - 'implementation("androidx.media3:media3-extractor:1.9.4")' # Supplies androidx.core.app.NotificationCompat, used by Maxi80MediaService to build the # MediaStyle foreground/lock-screen notification. Not pulled in transitively by media3. - - 'implementation("androidx.core:core-ktx:1.15.0")' + - 'implementation("androidx.core:core-ktx:1.16.0")' - 'implementation("com.google.guava:guava:31.1-android")' From 6765b498a95cc736a2c60aabc8fc9927b6dd1a4d Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Wed, 12 Aug 2026 13:50:24 +0200 Subject: [PATCH 2/2] =?UTF-8?q?fix(android):=20tighten=20R8=20keeps=20?= =?UTF-8?q?=E2=80=94=20scope=20keeppackagenames,=20replace=20blanket=20med?= =?UTF-8?q?ia3=20keep=20with=20targeted=20ExoPlayerImpl=20keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Android/app/proguard-rules.pro | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/Android/app/proguard-rules.pro b/Android/app/proguard-rules.pro index 6698b4e..4d3bbed 100644 --- a/Android/app/proguard-rules.pro +++ b/Android/app/proguard-rules.pro @@ -1,31 +1,20 @@ --keeppackagenames ** +# Skip framework packages must be kept verbatim — JNI looks them up by name. +-keeppackagenames maxi80.** +-keeppackagenames skip.** +-keeppackagenames tools.skip.** -keep class skip.** { *; } -keep class tools.skip.** { *; } --keep class kotlin.jvm.functions.** {*;} +-keep class kotlin.jvm.functions.** { *; } -keep class com.sun.jna.** { *; } -dontwarn java.awt.** -keep class * implements com.sun.jna.** { *; } -keep class * implements skip.bridge.** { *; } -keep class **._ModuleBundleAccessor_* { *; } -keep class maxi80.module.** { *; } -# Transpiled Maxi80Services classes are reached only via JNI-by-name from the native -# Swift bridge (e.g. PlatformEnvironment), so R8 can't see the reference and would -# strip/rename them — causing ClassNotFoundException at launch in minified builds. +# Transpiled Maxi80Services classes are reached only via JNI-by-name from the native Swift bridge. -keep class maxi80.services.** { *; } -# Media3 (ExoPlayer) surface used by the now-playing writeback. The phone playback path drives -# the notification metadata through the Skip JNI-by-name bridge: -# AndroidNowPlayingController.platformUpdateNowPlaying → player.getCurrentMediaItem / -# getCurrentMediaItemIndex / replaceMediaItem, rendered by DefaultMediaNotificationProvider from -# MediaItem.getMediaMetadata(). R8 can't see those by-name references in a minified release build -# and could strip/rename them, leaving the initial metadata stuck — matching issue #13. -# -# Deliberately broad (whole `androidx.media3.**`, not just `.common.**`) rather than relying on -# Media3's own consumer ProGuard rules: the by-name bridge reflects on the CONCRETE runtime type -# returned by SharedAudioPlayer.shared() — an ExoPlayer whose implementation lives in -# `androidx.media3.exoplayer` (ExoPlayerImpl), not `androidx.media3.common`. Scoping the keep to -# `.common.**` would leave the actually-reflected methods (getCurrentMediaItem / replaceMediaItem / -# getCurrentMediaItemIndex) on the impl class renamable, reintroducing the R8-strips-JNI-bridged- -# class crash. The keep is chosen over Media3's consumer rules for that reason. --keep class androidx.media3.** { *; } +# ExoPlayerImpl is the concrete class the JNI bridge receives from SharedAudioPlayer.shared(). +# Media3's own consumer ProGuard rules keep the rest of the public API. +-keep class androidx.media3.exoplayer.ExoPlayerImpl { *; } -dontwarn androidx.media3.**