./gradlew assembleDebug # builds to app/build/outputs/apk/debug/app-debug.apkNo build-time asset setup needed — proot/busybox/scripts are downloaded at runtime from CypherpunkArmory/UserLAnd-Assets-Ubuntu GitHub releases.
- Single module:
app/only. Package:com.ubuntuterminal. - Single Activity:
MainActivity.kthandles everything (UI, downloads, proot execution). - Runtime flow: App downloads pre-built assets + Ubuntu rootfs from UserLAnd-Assets-Ubuntu releases at first launch, extracts them to
filesDir/support/andfilesDir/rootfs/, then runs commands viasupport/execInProot.sh. - No bundled native binaries — everything is fetched at runtime.
- No tests, no lint, no formatting configured in the project.
- proot/busybox/scripts: Downloaded from
CypherpunkArmory/UserLAnd-Assets-Ubuntu(releasev0.0.12) - Ubuntu rootfs: Same release (
{arch}-rootfs.tar.gz) - No Gradle dependencies beyond
appcompatandmaterial
.github/workflows/build.yml: JDK 17, runs ./gradlew assembleDebug. Publishes APK as artifact and to continuous release tag on push to main/master.
- Assets are downloaded at runtime, not build time. First launch requires internet.
execInProot.shexpectsROOT_PATH,ROOTFS_PATH,LIB_PATHenv vars set by the caller.- The rootfs tarball may contain hardlinks — Android's tar can't create them, but the rootfs still works.