Repository navigation
feat(kotlin): publish a platform-independent alphaTab-core library for any JVM - #3018
Merged
Merged
Conversation
Prepares the split into a platform-independent core library (#2458): only the Android integration may depend on Android APIs. - EnvironmentPartials registers no Android render engine and prints no device details. AndroidEnvironment.initializeAndroid registers the "android" engine and the device lines instead; AlphaTabView calls it before it creates the API, so the log output is unchanged. - RegExp uses its own replacement loop on every API level instead of Matcher.replaceAll/replaceFirst(Function) on Android 14+. That path is what all JVM unit tests already ran. Unlike the JDK overloads it inserts the replacer result literally (JavaScript semantics), so a '$' or '\' in it no longer acts as a group reference on Android 14+. - The Java thread workers move to alphaTab.platform.jvm as they do not depend on Android.
The Kotlin target is split like the .NET one (AlphaTab + AlphaTab.Windows) so alphaTab can be used on any JVM, not only on Android (#2458). - New Gradle module :core (Kotlin/JVM) receives all transpiled code, the portable hand-written runtime and all tests. It is published as net.alphatab:alphaTab-core. Tests run as plain JUnit via :core:check. - :android keeps AlphaTabView and the Android platform code and is still published as net.alphatab:alphaTab. It depends on the core via api, so Android apps need no change. - The Android module reaches core internals through Kotlin friend paths, the counterpart of InternalsVisibleTo. Its Gradle module metadata pins alphaTab-core with a strict version, since internal members are not stable across versions. - The core compiles against the Java 17 class library (-Xjdk-release) and Animal Sniffer checks it against the Android API 26 signatures, so it cannot start using JDK APIs that Android lacks. - alphaSkia is an api dependency of the core: JVM applications call its native initialization themselves. - Explicit Kotlin module names avoid clashing META-INF/*.kotlin_module files in apps. - Shared publishing metadata and the version moved to the root build.
The Kotlin target now ships alphaTab-core for any JVM next to the Android library (#2458). The website follows the new split: - New page "Platforms and packages" lists every package per ecosystem with runtime, UI control, render engines and audio output. - "Getting Started (Android)" becomes "Getting Started (Kotlin)": installation-android is now installation-kotlin with both packages, a verified JVM rendering sample and the Android setup; the old address redirects. The Android configuration page stays. - The low-level API guide gets Kotlin examples next to JavaScript and C#. - Where "Android" stood for the Kotlin API in general it now reads "Kotlin": reference example tabs and name badges (JSDoc @example titles), Skia/SVG/font pages, feature catalog intros, introduction, landing texts and llms.txt. Pages about AlphaTabView, AudioTrack and the UI-bound api object keep "Android". - Release notes for 1.10 and the contributing guide describe the new packages and Gradle modules.
…tall snippet Maven coordinates are case-sensitive; net.alphatab:alphatab does not resolve, the artifact is net.alphatab:alphaTab.
…ilt for
The .NET and Kotlin install pages hard-coded package versions, which
went stale (the .NET page still showed 1.6.1). A remark plugin now
replaces {{alphaTabVersion}} and {{alphaSkiaVersion}} in code blocks and
inline code: the alphaTab version is the one the navbar and landing page
show, the alphaSkia version is read from the Kotlin version catalog that
alphaTab-core depends on. A leading backslash keeps a placeholder literal.
The MIDI events guide loads alphaTab from the @latest CDN tag like the
other pages instead of the @Alpha pre-release tag. The style guide
documents the placeholders.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
AI-authored disclosure (
alphatab-ai-authored-v1)Portions of this content were authored by an AI agent. The agent has read
AGENTS.md and the human submitter accepts responsibility for
compliance with the rules in that document.
Issues
Fixes #2458 (raised in discussion #2457)
Proposed changes
Until now, alphaTab for Kotlin was published only as the Android AAR
net.alphatab:alphaTab, although nothing below the UI integration depends on Android. JVM applications such as servers and command-line tools could not use it. This PR splits the Kotlin target the way the .NET target is split (AlphaTab+AlphaTab.Windows): a portable core plus the platform integration on top. There is no Kotlin Multiplatform setup and no second full compilation of the core. alphaTab's behaviour is unchanged, apart from the one regex detail described below.Packages
net.alphatab:alphaTab-core(new, JVM jar): all transpiled code, the portable hand-written runtime, and all tests. It runs on any JVM 17+ through the low-level APIs. There is no UI control, and no desktop JVM UI integration is planned.net.alphatab:alphaTab(Android AAR, same coordinates as before):AlphaTabViewand the Android platform code (canvas, audio, view containers, assets). It depends on the core viaapi, so existing Android apps need no change.How it is built (
packages/kotlin/src):core(Kotlin/JVM). The transpiler now writes intocore/src/{main,test}-generated.:core:check.:androidkeeps onlyAlphaTabView.ktandplatform/android/*.git mv, so their history is kept.InternalsVisibleTo("AlphaTab.Windows"). This keeps the TS@internalsurface, and with it the JS typings, unchanged.alphaTab-corewithstrictly <same version>, so a version mismatch fails at dependency resolution instead of on the device.update-version.mjs, the npm scripts and the nightly publish (root-levelpublishToMavenCentral) cover both artifacts.Keeping the core Android-compatible
The core no longer compiles against
android.jar. Two guards stop it from starting to use JDK APIs that Android lacks:-Xjdk-release=17restricts the code to the Java 17 class library, whichever JDK runs Gradle.gummy-bears-api-26signatures (the Android minSdk) runs in:core:check, whichnpm run test-kotlinnow calls.Two further changes protect consumers:
alphaTab-core,alphaTab-android) avoid clashingMETA-INF/*.kotlin_modulefiles in apps.apidependency of the core, because JVM applications call its native initialization (AlphaSkiaLinux.INSTANCE.initialize()etc.) themselves.Decoupling (separate commit, also builds in the old layout)
Three hand-written runtime files depended on Android:
EnvironmentPartialsno longer registers theandroidrender engine or prints device details.AndroidEnvironment.initializeAndroiddoes both now.AlphaTabViewcalls it before it creates the API, so the log output is unchanged.RegExp.replacealways uses its own replacement loop. Before, Android 14+ usedMatcher.replaceAll/replaceFirst(Function), and the JVM unit tests already ran the own loop. Behaviour change on Android 14+ only: the JDK overloads interpret$and\in the replacer result as group references, so a$in a song title used in a header/footer template (e.g. "Ke$ha") was treated as one. The replacer result is now inserted literally, as in JavaScript.alphaTab.platform.androidtoalphaTab.platform.jvm(internal types).Documentation (
website/)installation-androidis nowinstallation-kotlin, with both packages, a JVM rendering sample and the Android setup.#render-your-first-scoreanchor still resolves.@exampletitles; doc comments only), the Skia/SVG/font pages, the feature catalog intros, the introduction, the landing texts andllms.txt. Pages aboutAlphaTabView, AudioTrack and the UI-boundapiobject keep "Android".Two website fixes outside the strict scope of #2458 that came up while editing these pages:
net.alphatab:alphatab. Maven coordinates are case-sensitive, so that does not resolve; it is nowalphaTab.{{alphaTabVersion}}and{{alphaSkiaVersion}}in code blocks with the versions the site is built for. The MIDI events guide moves from the@alphaCDN tag to@latest.Verification
What actually ran, compared against a baseline build of
develop(17793fd)::android:testReleaseUnitTest) and after (:core:check). The sets of test names are identical.MatcherFunctionoverloads from the RegExp change are gone.android/androidxreferences.java.util.HexFormat(API 34) makes it fail, as intended.publishAllPublicationsToDistPathRepositoryproduced both artifacts with sources and Javadoc. The AAR's POM depends onalphaTab-corein compile scope, and its module metadata contains thestrictlyconstraint.alphaTab-core+alphaSkia-linuxfrom the dist repository.serenade.gp(4 tracks, 78 bars) and rendered it to PNG (alphaSkia) and SVG.assembleReleasesucceeds with no missing-class errors, and the APK contains the core code,Bravura.otfand the SoundFont assets.alphaTab-core:{strictly …}.npm run build-kotlin && npm run test-kotlinsucceed.npm run build-websitesucceeds, including the broken-link check, after building the alphaTab dist from this branch. The rendered pages show the substituted versions, the Kotlin tabs and the redirect.Observations outside this PR
Found while verifying; none of these are changed here:
installation-netcreates aScoreRendererwith lazy loading enabled and never callsrenderResult, so it likely receives no partial results.EventEmitterwhen implementingISynthOutput.Checklist
:core, the Animal Sniffer API-26 check is new, and the published artifacts were verified with the consumer projects above.AI authorship disclosure
(
alphatab-ai-authored-v1) is present at the top of this body, and I havepersonally reviewed every change and can explain each one
Further details
website/