Skip to content

feat(android adapter): add an android client backed by SendspinDroid - #161

Closed
chrisuthe wants to merge 2 commits into
Sendspin:mainfrom
chrisuthe:chrisuthe/task/add-an-android-client-adapter-backed-by
Closed

chrisuthe wants to merge 2 commits into
Sendspin:mainfrom
chrisuthe:chrisuthe/task/add-an-android-client-adapter-backed-by

Conversation

@chrisuthe

Copy link
Copy Markdown
Member

Adds android, a client-only implementation backed by SendspinDroid. This is the first of four steps toward replacing the sendspin-jvm client; sendspin-jvm stays until the last one. Part of Sendspin/backlog#70.

What changes

  • Adapter (adapters/android/client/): a Kotlin/JVM Gradle project, ported from SendspinDroid's own conformance-client.
    • It builds SendspinDroid's Kotlin Multiplatform :shared module from repos/SendspinDroid through a composite build, using the clone's own Gradle wrapper.
    • It runs on the app's handshake driver, Noise wire codec, MessageBuilder and MessageParser.
    • It is launched as a fat jar by src/conformance/adapters/android_client.py.
  • Advertised formats: client/hello comes from the app's MessageBuilder.buildSupportedFormats, not a hand-written list.
    • The scenario's preferred codec is the app's preferred-codec input.
    • Bit depths are those of an API 31+ device: 48 kHz stereo and mono PCM at 32, 24 and 16 bits, behind the one preferred compressed codec.
  • Format preference: the preferred format is sent in every client/state once set, as the app's protocol handler does.
  • Evidence:
    • PCM is hashed from the decrypted frames.
    • FLAC and OPUS are decoded only by Android MediaCodec, so the adapter reports encoded hashes and the codec header, and decoded audio is not judged.
  • Build: _gradle_build_result now takes the adapter and repository, so sendspin-jvm and android share it.
  • Report links: repository_versions.py takes each implementation's link from the registry's remote_url instead of assuming the Sendspin organization. Every existing row's link is unchanged; android links chrisuthe/SendspinDroid.
  • CI: publish.yml adds android to the client list and installs JDK 21 alongside 17. The macos-26 image already provides ANDROID_HOME with android-36, which SendspinDroid's Gradle settings need to configure.

Results

Run locally against aiosendspin and sendspin-server-cpp:

Scenario Result Cause
client-initiated-state-format-pcm passes on both Renegotiates from 32-bit to 16-bit PCM.
client-initiated-pcm fails on both, PCM hash mismatch The app advertises 48 kHz only and the fixture is 8 kHz mono, so the server resamples and the canonical hash cannot match. This follows from what the app advertises, not from the harness.
client-initiated-state-format-flac fails on both The app lists its preferred codec ahead of PCM and offers no other codec, so it cannot advertise the PCM-then-FLAC order the scenario starts from. The adapter still takes part, then fails with that reason. Tracked in chrisuthe/SendspinDroid#336.

Known differences from the app

  • The adapter drives :shared with its own session logic, because the app's SendSpinProtocolHandler lives in the Android-bound :player module.
  • As a result it reports available: true straight after activation, where the app waits for clock sync.

…red with

The report linked every implementation to github.com/Sendspin/<repo_dirname>,
so an implementation hosted outside the Sendspin organization would be linked
to a repository that does not exist. Take the link from the registry's
remote_url instead; every current entry resolves to the same URL as before.
Add the android implementation, a client-only entry for SendspinDroid. Its
adapter in adapters/android/client is a Kotlin/JVM Gradle project that pulls
SendspinDroid's :shared protocol module from repos/SendspinDroid through a
composite build, and is launched as a fat jar by a thin Python wrapper.

client/hello is built with the app's MessageBuilder, its formats taken from
buildSupportedFormats with the scenario's preferred codec, so the matrix shows
what the app really advertises. The Gradle build helper now takes the
adapter and repository, so the sendspin-jvm and android adapters share it.

CI adds android to the client list and installs JDK 21 alongside 17. The
macos-26 image already provides the Android SDK the composite build needs.
@chrisuthe chrisuthe closed this Oct 14, 2026
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.

1 participant