--- name: course-to-apk description: Package an existing interactive course generated by the book-to-course skill (a folder with index.html, assets/ and course/data.js, or its .zip) into a signed Android APK — a light offline WebView app to install on a phone or tablet. Checks the build tools on the machine (JDK, Android SDK build-tools and platform), tells the user exactly what is missing and where to get it, and can download it for them. Use this whenever the user wants a course "na telefon/tablet", "na Androida", "jako aplikację", "zrób z kursu APK", "course to apk", wants to learn from their generated course on a mobile device offline, or wants to rebuild/update a course app after adding chapters — even if they don't say "APK" explicitly. Do NOT use for building a course from a book (that is book-to-course), for iOS apps, or for general Android app development. --- # Course → Android APK Wraps a finished book-to-course course into a small Android app: one Activity with a WebView that serves the course files from inside the APK. No Gradle, no Android Studio project, no network permission — the build calls the SDK tools directly (`aapt2 → javac → d8 → zipalign → apksigner`), so the APK is roughly the size of the course plus ~10 KB. The app wrapper (`assets/android/`) and the scripts are fixed and tested — **your job is the conversation around them**: find the course, get the toolchain in place with the user's consent, build, and explain how to put it on the device. | script (in `scripts/`) | purpose | |---|---| | `toolchain.py [--json]` | what is installed, what is missing, where to download it; exit 0 = ready | | `setup_toolchain.py --dry-run` | list exactly what would be downloaded (name, size, URL) — downloads nothing | | `setup_toolchain.py --show-license` | print the Android SDK licence text | | `setup_toolchain.py --accept-licenses` | download only the missing parts into `~/.local/share/course-to-apk` (no sudo) | | `build_apk.py COURSE_DIR [--install]` | build the signed APK into `-android/` | All scripts are Python 3 standard library only. ## Workflow ### 1. Find the course A course folder has `index.html`, `assets/app.js` and `course/data.js`. Look where the user points, in the current directory, or among recent book-to-course output. If they give a `.zip` (from `pack_course.py`), unzip it next to the zip first — it contains one top folder named after the course; that folder is COURSE_DIR. If `content/` exists but `course/data.js` is missing or older than the lessons, the course was not rebuilt — run book-to-course's `build_course.py COURSE_DIR` first (when that skill is available), otherwise ask the user to. ### 2. Check the toolchain ```bash python3 scripts/toolchain.py ``` It searches well beyond PATH (JAVA_HOME, ANDROID_HOME, `~/Android/Sdk`, `~/.jdks`, Android Studio's bundled JBR, `/usr/lib/jvm`, …), so a JDK that `which java` does not see is still found. If it prints **READY**, go to step 4. ### 3. Something is missing → ask, don't assume Tell the user, in their language, what is missing — use the report's lines, they already contain the official download links and package-manager commands for their OS. Then run `setup_toolchain.py --dry-run` so you can quote the real sizes and URLs, and ask them to choose (AskUserQuestion works well here): - **"I'll install it myself"** — give the list again as a short checklist (what, where from, and that a non-standard location needs `JAVA_HOME` / `ANDROID_HOME`). Then **stop and wait**. Do not poll, do not build, do not download anything. When they write that it's installed, rerun `toolchain.py`; if something is still missing, say exactly what and wait again. - **"Download it for me"** — the Android SDK packages are under the Android SDK License Agreement (https://developer.android.com/studio/terms; full text via `--show-license`). Their choice of this option must include agreeing to it — say so in the question. Only then run `python3 scripts/setup_toolchain.py --accept-licenses` (≈320 MB if the JDK is also missing, ≈125 MB otherwise; it verifies checksums and installs only into `~/.local/share/course-to-apk`, nothing system-wide, no sudo). Why the care: downloading hundreds of megabytes and accepting a licence are the user's decisions, not yours, and a user who said they'd install things themselves is mid-installation — building or downloading behind their back collides with that. ### 4. Build ```bash python3 scripts/build_apk.py "" ``` Defaults that are right for almost everyone — mention them, don't ask: - **Output** `-android/.apk`, next to the course folder; `apk.json` there remembers the package id, label, icon colour and an auto-incremented versionCode. - **Signing** with the Android debug key `~/.android/debug.keystore` (the standard developer certificate; created with keytool if it doesn't exist). Fine for installing on your own devices; it is not a Play Store release key. If the user has their own keystore: `--keystore FILE --key-alias A --ks-pass P` (or `APK_KS_PASS` env var so the password doesn't land in shell history); it's remembered in `apk.json`. - **Package id** `net.booktocourse.`, **label** = course title. Override with `--package` / `--label` only when asked — changing the package later makes Android treat it as a different app and the learner loses progress. - **Android 7.0+** (minSdk 24); targetSdk = the newest platform installed. If the build fails, the error names the tool and shows its output; see `references/troubleshooting.md`. ### 5. Hand it over Tell the user in a few lines: where the APK is (absolute path), its size, and how to install it: - **Copy to the device** (USB cable, cloud drive, e-mail to yourself), open the file on the device, allow "install unknown apps" for the app that opens it when Android asks; Play Protect may warn about an unknown developer → "Install anyway". - **Or over USB with adb**: enable Developer options → USB debugging, connect, then `build_apk.py … --install` (or `adb install -r `). Offer this if `toolchain.py` showed adb and a device is connected (`adb devices`). Also say, briefly: - Progress is stored inside the app on the device (not in `progress/progress.json` of the computer copy) and survives updates — **rebuild with the same folder and key** after adding chapters and install over the old app. Uninstalling deletes it. - Code exercises: the "Run tests" button needs the computer version (`start.sh`/`start.bat`); on the phone the page shows the test command instead. Lessons, quizzes, tests and flashcards all work offline. ## What the app does (so you can answer questions) - Serves the course from `https://appassets.androidplatform.net/` via `shouldInterceptRequest` — a reserved host that never hits the network, giving the page a stable origin for `localStorage`. No INTERNET permission; links to other sites open in the user's browser. - Back button/gesture goes back through the course's history, then closes the app; edge-to-edge insets (status bar, cutouts, keyboard) are handled; dark/light follows the system on first launch, then the course's own theme toggle. - `alert()`/`confirm()` show real dialogs (the player avoids them anyway). To change the wrapper itself (e.g. lock orientation), edit `assets/android/` — `MainActivity.java`, `AndroidManifest.xml` (placeholders `{{PACKAGE}}`, `{{LABEL}}`), `res/`. Keep it framework-only: there is no Gradle, so AndroidX libraries can't be added.