#!/bin/bash # Builds Plexamp Lite without the Android SDK or Gradle, one APK per Android level (same package and key): # build/PlexampLite.apk Android 2.2 and later (Galaxy Mini) src + platform/api8, against android-8 # build/PlexampLite-api16.apk Android 4.1 and later (Xperia J...) src + platform/api16 + ExoPlayer, against android-16 # Each: aapt2 (resources; api16 overlays platform/api16/res) -> javac (Java 8 bytecode) -> then # api8: Dalvik 2.x link check -> dx (dex 035) # api16: R8 (shrinks ExoPlayer and Guava, desugars Java 8, dex 035 for Android 4.1) # -> signapk.py (v1 / SHA-1 in the classic SignApk format, plus zipalign). # versionCode = the manifest's x 100 + the level, so a phone that moves up to Android 4.1 gets the newer build as an update. # Toolchain: tools/setup_toolchain.sh, plus tools/fetch_exoplayer.sh and R8 (d8.jar from build-tools 34) for api16. # ./build.sh both # ./build.sh 16 one level set -euo pipefail cd "$(dirname "$0")" T=${TOOLS:-$HOME/android-toolchain} BC_SRC=$T/bcsrc EXO=$T/exoplayer-2.18.7 R8=${R8:-$T/calendar-tools/d8.jar} # build-tools' d8.jar holds R8 too PY=${PY:-$T/venv/bin/python} # signapk.py needs the cryptography package [ -x "$PY" ] || PY=python3 LEVELS=${*:-8 16} # a JDK 11+ (R8 needs it): the macOS java stub answers "javac" but can't run it if ! javac -version >/dev/null 2>&1 || javac -version 2>&1 | grep -q '1\.8'; then for j in "${JAVA_HOME:-}" /opt/homebrew/opt/openjdk@17 /opt/homebrew/opt/openjdk $(ls -d "$HOME"/tools/jdk-17* 2>/dev/null); do if [ -n "$j" ] && [ -x "$j/bin/javac" ]; then export JAVA_HOME=$j PATH=$j/bin:$PATH; break; fi done fi echo "== strings" python3 tools/strings.py echo "== text fit check (240x320, all languages and sizes)" if [ -f "$T/fonts/droidsans-regular.ttf" ]; then "$PY" tools/check_fit.py "$T/fonts" || { echo "Some texts don't fit their space (see above)"; exit 1; } else echo "(skipped: run tools/setup_toolchain.sh to fetch the Droid Sans font)" fi CODE=$(sed -n 's/.*android:versionCode="\([0-9]*\)".*/\1/p' AndroidManifest.xml) for API in $LEVELS; do case $API in 8) TARGET=10; APK=build/PlexampLite.apk ;; 16) TARGET=16; APK=build/PlexampLite-api16.apk [ -f "$EXO/exoplayer-core.jar" ] || { echo "no ExoPlayer in $EXO: run tools/fetch_exoplayer.sh"; exit 1; } [ -f "$R8" ] || { echo "no R8 at $R8 (build-tools 34's lib/d8.jar): set R8="; exit 1; } ;; *) echo "no such level: $API (8 or 16)"; exit 1 ;; esac ANDROID_JAR=$T/platforms/android-$API/android.jar OUT=build/api$API echo "== Android level $API -> $APK (versionCode $((CODE * 100 + API)))" rm -rf $OUT && mkdir -p $OUT/res $OUT/gen $OUT/classes sed -e "s/android:minSdkVersion=\"[0-9]*\"/android:minSdkVersion=\"$API\"/" \ -e "s/android:targetSdkVersion=\"[0-9]*\"/android:targetSdkVersion=\"$TARGET\"/" \ AndroidManifest.xml > $OUT/AndroidManifest.xml $T/aapt2 compile --dir res -o $OUT/res/compiled.zip OVERLAY= if [ -d platform/api$API/res ]; then $T/aapt2 compile --dir platform/api$API/res -o $OUT/res/overlay.zip OVERLAY="-R $OUT/res/overlay.zip" fi $T/aapt2 link -o $OUT/base.apk -I $ANDROID_JAR --manifest $OUT/AndroidManifest.xml \ --java $OUT/gen -A assets --version-code $((CODE * 100 + API)) --replace-version \ --no-version-vectors $OUT/res/compiled.zip $OVERLAY LIBS= [ $API -ge 16 ] && LIBS=$(ls $EXO/*.jar | tr '\n' ':') find src platform/api$API $OUT/gen -name '*.java' > $OUT/sources.txt javac -nowarn -Xlint:-options -source 8 -target 8 -encoding UTF-8 -g:source,lines \ -bootclasspath $ANDROID_JAR -classpath "$LIBS" -sourcepath "src:platform/api$API:$BC_SRC:$OUT/gen" \ -d $OUT/classes @$OUT/sources.txt 2>&1 | grep -v -E '^Picked up|^Note:|^warning: Cannot find annotation|^ reason: class file for|^[0-9]+ warnings?$' || true test -f $OUT/classes/com/minamp/HomeActivity.class if [ $API -lt 11 ]; then echo "-- Dalvik 2.x link check" python3 tools/scan_dalvik.py $OUT/classes $ANDROID_JAR > $OUT/dalvik-scan.txt if ! grep -q "^total patterns: 0$" $OUT/dalvik-scan.txt; then cat $OUT/dalvik-scan.txt; echo "Calls Android 2.x can't link (see above): fix before shipping"; exit 1 fi java -Xmx2g -jar $T/dx.jar --dex --output=$OUT/classes.dex $OUT/classes 2>&1 | grep -v '^Picked up' || true else echo "-- R8" (cd $OUT/classes && zip -q -r ../app.jar .) PGCONF=$(for f in tools/r8-rules.pro $EXO/*.pro; do printf -- '--pg-conf %s ' "$f"; done) java -Xmx2g -cp "$R8" com.android.tools.r8.R8 --release --min-api $API --lib $ANDROID_JAR \ --map-diagnostics info none --output $OUT $PGCONF $OUT/app.jar $EXO/*.jar 2>&1 | grep -v '^Picked up' || true test -f $OUT/classes.dex # one dex only: Android 4.1 can't load a second without a multidex library if [ -f $OUT/classes2.dex ]; then echo "R8 made more than one dex file (over 64K methods)"; exit 1; fi fi cp $OUT/base.apk $OUT/unsigned.apk (cd $OUT && zip -q unsigned.apk classes.dex) # v1 signature in the classic Android SignApk format (jarsigner's modern output won't install on Android <= 4.2) $PY tools/signapk.py ${KEYSTORE:-signing/minamp.keystore} ${KEYPASS:-minamp123} $OUT/unsigned.apk $APK ls -l $APK done