Build from source

No Gradle, no IDE: shell scripts and the SDK's command-line tools.

Requirements

  • Android SDK with platform 34 and any build-tools (set ANDROID_HOME, or use ~/Library/Android/sdk)
  • JDK 17 or newer
  • Go (version in warp/go.mod) and the Android NDK (any recent one, from the SDK manager or ANDROID_NDK_HOME) for the WARP helper
  • curl, zip, openssl

Build

git clone https://github.com/fmhyplay/android
cd android
warp/build.sh     # builds the WARP helper into jni/ with the NDK
./build.sh        # downloads the data files, then builds both APKs

You get FMHYPlay-TV-vX.Y.Z.apk and FMHYPlay-Android-vX.Y.Z.apk. On the first run build.sh creates a signing key (release.jks and release.pass). Keep it: a release signed with another key cannot update an installed one.

VERSION_NAME and VERSION_CODE can be set in the environment. TEST_EXPORT=1 ./build.sh builds emulator test APKs instead (below).

Project layout

PathWhat is in it
src/me/champdev/weblock/The app (plain Java): Home (tabs), WebActivity (the browser), PlayerActivity (the player), Sniffer (stream detection), Iptv*, Catalog, Sites, Warp, AdBlock
assets/Scripts injected into pages: frame.js (server, quality and episode finder, stream sniffing), spatnav.js (remote navigation), roles.js, autosearch.js
warp/The Go helper: a userspace WireGuard client exposing a local HTTP proxy
libs/Media3, AndroidX WebKit and Guava as plain jars
res/Icons, drawables, theme
scripts/fetch-assets.shDownloads the site lists and blocklist the app starts with (they are not stored in the repository)
.github/workflows/CI and release workflows

Signing

Android only installs an update when it is signed with the same key as the installed app, so the release key is permanent. To use one key locally and on GitHub:

# encode the key once
base64 -i release.jks | pbcopy        # macOS; on Linux: base64 -w0 release.jks
# then add two repository secrets (Settings, Secrets and variables, Actions):
#   KEYSTORE_B64   the base64 text
#   KEYSTORE_PASS  the contents of release.pass
Never commit release.jks or release.pass. .gitignore already excludes them; back them up somewhere private.

GitHub Actions

Actions runs your commands on a GitHub-hosted Linux machine that already has the Android SDK and Java. Because the build is only shell commands, nothing else is needed.

  • Build (.github/workflows/build.yml): on every push and pull request it builds the WARP helper and both APKs and uploads them as a downloadable artifact. Without the signing secrets (forks, pull requests) it uses a throw-away key, which is fine for checking that the code builds.
  • Release (.github/workflows/release.yml): see below. It refuses to run without the signing secrets.

Publish a release

git tag v2.12.0
git push origin v2.12.0

The workflow takes the version from the tag (v2.12.0 becomes version name 2.12.0 and version code 21200, so codes always rise with the tag), builds and signs both APKs, writes SHA256SUMS.txt and creates the GitHub release with that version's section of CHANGELOG.md as its notes, so write it before you tag. Build releases only this way, so the version codes stay in order.

Emulator testing

TEST_EXPORT=1 ./build.sh builds FMHYPlay-TV-test.apk and FMHYPlay-Android-test.apk. They export the browser and IPTV screens so you can open a test page from the command line, and the TV one also answers the Home key (an emulator image without a launcher shows a black screen otherwise).

adb shell am start -n me.champdev.weblock/.WebActivity \
  --es site Test --es siteUrl http://10.0.2.2:8000/ --es url http://10.0.2.2:8000/test.html