#!/bin/sh # Builds the updater app's own APK. # # ./build-apk.sh # # The APK pins the CA on *this* machine ($XDG_CONFIG_HOME/dev-updater/certs/ca.pem, # or DEV_UPDATER_CA), so build it on the machine that runs the server: an app # built somewhere else trusts a CA that server can't present, and simply won't # connect. Start dev-updater once first if there are no certificates yet -- it # generates them --; the build stops with that instruction if it can't find one. # # Unlike ./run-android.sh, this touches no emulator: it only produces the file. # This is the updater itself, so a fresh install can't come *through* the # updater: serve it over the plain-HTTP bootstrap port instead # (dev-updater --download) and open http://:8091 on the phone. set -eu SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) cd "$SCRIPT_DIR" # Prefer an SDK this machine has already configured -- the host and the dev # VM don't keep it in the same place, and android-env.sh is written for the # VM's layout (it also installs missing packages, which isn't wanted here). if [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}" ]; then echo "==> Using ANDROID_HOME=$ANDROID_HOME" elif [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "${ANDROID_SDK_ROOT}" ]; then ANDROID_HOME="$ANDROID_SDK_ROOT" export ANDROID_HOME echo "==> Using ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" elif [ -d "$HOME/Android/Sdk" ]; then ANDROID_HOME="$HOME/Android/Sdk" ANDROID_SDK_ROOT="$ANDROID_HOME" export ANDROID_HOME ANDROID_SDK_ROOT echo "==> Using $ANDROID_HOME" else echo "No Android SDK found. Set ANDROID_HOME to it, or install one" >&2 echo "(Android Studio's default location is ~/Android/Sdk)." >&2 exit 1 fi CA="${DEV_UPDATER_CA:-${XDG_CONFIG_HOME:-$HOME/.config}/dev-updater/certs/ca.pem}" if [ -f "$CA" ]; then # Printed so a wrong or stale certificate is visible here rather than as # a handshake failure on the phone: it should match the CA the server # you are going to talk to generated, which is the one in the directory # named above unless DEV_UPDATER_CA points elsewhere. FINGERPRINT=$(openssl x509 -in "$CA" -pubkey -noout 2>/dev/null \ | openssl pkey -pubin -outform der 2>/dev/null \ | openssl dgst -sha256 -binary 2>/dev/null \ | openssl base64 2>/dev/null || echo "(openssl unavailable)") echo "==> Pinning the CA at $CA" echo " fingerprint: $FINGERPRINT" else echo "No CA certificate at $CA -- run the server on this machine" >&2 echo "first, or set DEV_UPDATER_CA to one. The APK has to embed it at build time." >&2 exit 1 fi echo "==> Building" # Dev Updater ships a wrapper that turns a Gradle build into the # `@@progress done/total` lines its cards draw a real bar from, and points # $DEV_UPDATER_PROGRESS at it when it is the one running this. Gradle # cannot report a count any other way -- see the wrapper's own header -- # and having it there rather than here is what stops every project copying # the same twenty-five lines of counting. Built by hand, the variable is # unset and the build simply runs. if [ -x "${DEV_UPDATER_PROGRESS:-}" ]; then "$DEV_UPDATER_PROGRESS" gradle ./gradlew :androidApp:assembleDebug else ./gradlew :androidApp:assembleDebug fi APK="$SCRIPT_DIR/androidApp/build/outputs/apk/debug/androidApp-debug.apk" echo echo "==> Built $APK" [ -f "$APK" ] && ls -lh "$APK" | awk '{print " " $5}' echo echo "To get it onto the phone:" echo " - if the installed copy still trusts this CA, hit Update on the" echo " 'Dev Updater' entry in the app itself;" echo " - if the CA was regenerated, the installed copy can no longer reach" echo " the server, so reinstall over the bootstrap port instead:" echo " dev-updater --download" echo " then open http://:8091 in the phone's browser."