Files
calendar-lite/build.sh
T

102 lines
4.6 KiB
Bash
Executable File

#!/bin/sh
# Builds CalendarLite.apk for Android 2.3 (API 10) without Gradle.
#
# Needs: JDK 11+ (javac, keytool), python3, and three tools:
# D8 command that runs d8 (Android SDK build-tools; default "d8" on PATH)
# APKTOOL path to apktool.jar (https://apktool.org; bundles aapt and smali)
# APKSIGNER path to apksigner.jar (Android SDK build-tools/<ver>/lib/apksigner.jar)
# Optional:
# ANDROID_JAR a real platforms/android-10/android.jar; otherwise ./stubs is used to compile
# KEYSTORE signing keystore (created on first build; keep it so updates install over)
set -eu
cd "$(dirname "$0")"
OUT=build
# defaults: the copies in ~/android-toolchain/calendar-tools (build-tools 34's d8.jar and apksigner.jar, apktool 2.9.3)
CT=${CALENDAR_TOOLS:-$HOME/android-toolchain/calendar-tools}
if [ -z "${D8:-}" ] && [ -f "$CT/d8.jar" ]; then D8="java -cp $CT/d8.jar com.android.tools.r8.D8"; fi
D8=${D8:-d8}
if [ -z "${APKTOOL:-}" ] && [ -f "$CT/apktool_2.9.3.jar" ]; then APKTOOL=$CT/apktool_2.9.3.jar; fi
if [ -z "${APKSIGNER:-}" ] && [ -f "$CT/apksigner.jar" ]; then APKSIGNER=$CT/apksigner.jar; fi
if ! command -v javac >/dev/null 2>&1; then
for j in "${JAVA_HOME:-}" /opt/homebrew/opt/openjdk@17 /opt/homebrew/opt/openjdk; do
if [ -n "$j" ] && [ -x "$j/bin/javac" ]; then JAVA_HOME=$j; PATH=$j/bin:$PATH; export JAVA_HOME PATH; break; fi
done
fi
APKTOOL=${APKTOOL:?set APKTOOL=/path/to/apktool.jar}
APKSIGNER=${APKSIGNER:?set APKSIGNER=/path/to/apksigner.jar}
KS=${KEYSTORE:-gingercal.keystore}
BC_SRC=${BC_SRC:-$HOME/android-toolchain/bcsrc} # Bouncy Castle renamed to com.minamp.bc (Minamp's tools/setup_toolchain.sh)
VERSION_CODE=$(sed -n 's/.*android:versionCode="\([0-9]*\)".*/\1/p' AndroidManifest.xml)
VERSION_NAME=$(sed -n 's/.*android:versionName="\([^"]*\)".*/\1/p' AndroidManifest.xml)
rm -rf "$OUT"
mkdir -p "$OUT/stubs" "$OUT/classes" "$OUT/dex" "$OUT/apk/res"
# 0. every interface string must have its Galician translation
python3 tools/check_i18n.py .
# 1. compile
if [ -n "${ANDROID_JAR:-}" ]; then
CP="$ANDROID_JAR"
else
javac -nowarn -Xlint:none --release 8 -d "$OUT/stubs" $(find stubs -name "*.java") 2>/dev/null
CP="$OUT/stubs"
fi
# Java 8 bytecode, Java 6-era APIs only (Android 2.3 runs a Harmony class library).
javac --release 8 -encoding UTF-8 -Xlint:-options -nowarn -cp "$CP" -sourcepath "src:android:$BC_SRC" \
-d "$OUT/classes" $(find src android -name '*.java')
python3 tools/strip_method_params.py $(find "$OUT/classes" -name '*.class')
# 2. dex (format 035 for Dalvik), then disassemble so smali re-assembles a clean dex
$D8 --min-api 9 --release --output "$OUT/dex" $(find "$OUT/classes" -name '*.class') >"$OUT/d8.log" 2>&1 \
|| { cat "$OUT/d8.log"; exit 1; }
mkdir -p "$OUT/tools"
javac -nowarn -cp "$APKTOOL" -d "$OUT/tools" tools/Disassemble.java
java -cp "$APKTOOL:$OUT/tools" Disassemble "$OUT/dex/classes.dex" "$OUT/apk/smali" 8
# 3. resources + manifest, compiled by real aapt (v1, the tool of the Gingerbread era)
cp AndroidManifest.xml "$OUT/apk/"
cp -r res/* "$OUT/apk/res/" # launcher icon (ldpi..xhdpi) and the status-bar reminder icon
cp -r assets "$OUT/apk/" # Mozilla root certificates for the bundled TLS
cat > "$OUT/apk/apktool.yml" <<EOF
version: 2.9.3
apkFileName: CalendarLite.apk
isFrameworkApk: false
usesFramework:
ids:
- 1
tag: null
sdkInfo:
minSdkVersion: 8
targetSdkVersion: 10
packageInfo:
forcedPackageId: 127
renameManifestPackage: null
versionInfo:
versionCode: $VERSION_CODE
versionName: $VERSION_NAME
resourcesAreCompressed: false
sharedLibrary: false
sparseResources: false
doNotCompress:
- resources.arsc
- png
EOF
java -jar "$APKTOOL" -q b --use-aapt1 -api 8 -f -o "$OUT/unsigned.apk" "$OUT/apk"
# 4. sign. Android < 4.3 needs a plain v1 (JAR) signature with SHA-1 and no PKCS#7 signed
# attributes; apksigner picks exactly that for --min-sdk-version 8. (jarsigner does not.)
if [ ! -f "$KS" ]; then
keytool -genkeypair -keystore "$KS" -storetype PKCS12 -storepass android -keypass android \
-alias gingercal -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -validity 10000 -dname "CN=Calendar Lite" 2>/dev/null
fi
java -jar "$APKSIGNER" sign --ks "$KS" --ks-key-alias gingercal --ks-pass pass:android --key-pass pass:android \
--min-sdk-version 8 --v1-signing-enabled true --v2-signing-enabled false --v3-signing-enabled false \
--v4-signing-enabled false --out "$OUT/signed.apk" "$OUT/unsigned.apk"
python3 tools/zipalign.py "$OUT/signed.apk" CalendarLite.apk
# 5. refuse to ship anything Android 2.3 would reject
java -jar "$APKSIGNER" verify --min-sdk-version 8 --max-sdk-version 10 CalendarLite.apk
python3 tools/check_dex.py CalendarLite.apk
ls -l CalendarLite.apk