The proxy can now be started and stopped from inside another process — the
accept loop lives in the library — and there is an Android app that uses that
surface instead of spawning the CLI. This release carries the app as APK
assets, so running a proxy on a phone no longer means installing Termux.
Why
On phones the useful deployment is not Termux plus a shell script: it is a
single APK with a text field for the same flags the binary already accepts, a
start/stop button, and a tap that opens the printed tg://proxy link in
Telegram. That only works if the core can run as a library, not just as
tg-ws-proxy.
Android app
Assets on this release, one per ABI plus a universal build:
| Asset | Take this one if |
|---|---|
tg-ws-proxy-rs-android-2.3.0-universal.apk
| you are not sure — it carries all three ABIs |
tg-ws-proxy-rs-android-2.3.0-arm64-v8a.apk
| any phone from roughly 2016 on (~⅓ the size) |
tg-ws-proxy-rs-android-2.3.0-armeabi-v7a.apk
| an older 32-bit device |
tg-ws-proxy-rs-android-2.3.0-x86_64.apk
| an emulator or an x86 tablet |
Requires Android 8.0 (API 26) or newer. Installing a per-ABI APK on the wrong
architecture fails at first launch, so take the universal one when in doubt.
If the asset names end in -unsigned, this release was built without
signing secrets: Android refuses to install an unsigned APK by any route,
including adb install, and you would have to sign it yourself first.
In the app, type the flags you would pass to tg-ws-proxy, tap Start, and
tap the tg://proxy link when it appears. The listen address should stay
127.0.0.1 so Telegram on the same phone can reach it. Add --secret <32 hex chars> if you want the link to survive restarts. Logs are hidden by the
prefilled --quiet; drop it to see them.
The application id is io.github.valnesfjord.tgwsproxyrs. It has no released
predecessor, so nothing installs over anything.
Added
tg_ws_proxy_rs::server::run/run_with_listen— the CLI's bind, banner,
pool warm-up and accept loop, with a shutdown future so an embedder can stop
it.--port 0now reports the real bound port in thetg://link.Config::try_from_cli_line— parse one shell-style argument string the same
way the binary parses argv (including a leading./tg-ws).- An Android Jetpack Compose app in
android/that loads the core as
libtg_ws_proxy_jni.so, runs it in a foreground service, shows the log, and
opens the proxy link. Log/tg://callbacks use a class reference cached
while the app class loader is still in scope —FindClassfrom a Tokio
worker would otherwise throwClassNotFoundExceptionand kill the process.
See Android.md. SHA256SUMSnow covers every asset on the release. It used to be built from
one packaging job's own staging directory, so the macOS and Windows archives
were never in it; the APKs would not have been either.
The CLI flags, TG_* environment variables and the on-the-wire protocol are
unchanged. tg-ws-proxy is still the same binary; main.rs is now a thin
wrapper around server::run.
Cost
The JNI shim lives in its own crate (crates/android-jni) so the library
everything else depends on stays a plain rlib — a cdylib there would have made
every desktop and Docker cargo build link an .so nobody loads. The repository
is now a two-member Cargo workspace whose default-members is the root package
alone, so nothing about a normal build or the release binaries changes. jni is
pulled in only when compiling that crate for target_os = "android".