Podlite 1.12: a build for Android 4.1 (Xperia J) with ExoPlayer, speed and skip silences
- One build per Android level, as in Tenda and Plexamp Lite: build/Podlite.apk (Android 2.2+, versionCode 1308) and build/Podlite-api16.apk (Android 4.1+, 1316), from shared src/ plus platform/api8 or platform/api16; build.sh now runs on the local toolchain (aapt2, dx or R8, signapk.py; the JKS key converted for the run). - Android 4.1 build: ExoPlayer 2.18.7 behind an Engine interface, with playback speed (player header) and skipping silences (Settings), a 3-minute buffer and MediaPlayer as fallback for audio it can't decode; a notification and lock screen with the cover and buttons; Holo; a menu button on phones without a Menu key; metered networks for "download on Wi-Fi only". - Both builds: tlskit's Http.abort fix (a finished response's pooled connection is no longer closed under a later request); the lock screen's and newer headsets' play/pause keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b2ca212c45
commit
666a7eb8cd
32 files changed
+1267
-123
No files matched your search
@@ -1,38 +1,104 @@
|
||||
#!/bin/sh
|
||||
# Builds Podlite.apk for Android 2.2+ (API 8) using the plain SDK tools, no Gradle.
|
||||
# ANDROID_JAR android.jar for API 8 (compiling against it guarantees no newer APIs sneak in)
|
||||
# KEYSTORE signing keystore (created on first build if missing)
|
||||
set -e
|
||||
#!/bin/bash
|
||||
# Builds Podlite without the Android SDK or Gradle, one APK per Android level (same package and key):
|
||||
# build/Podlite.apk Android 2.2 and later (Galaxy Mini) src + platform/api8, against android-8
|
||||
# build/Podlite-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; Android <= 4.2 rejects jarsigner's).
|
||||
# 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, default ~/android-toolchain) from Plexamp Lite's tools/setup_toolchain.sh, plus tools/fetch_exoplayer.sh,
|
||||
# the android-16 jar and R8 (d8.jar from build-tools 34) for api16.
|
||||
# ./build.sh both
|
||||
# ./build.sh 16 one level
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
ANDROID_JAR=${ANDROID_JAR:-/home/claude/sable/android-platforms/android-8/android.jar}
|
||||
KEYSTORE=${KEYSTORE:-miniabs.keystore}
|
||||
BC_SRC=${BC_SRC:-$HOME/android-toolchain/bcsrc} # Bouncy Castle renamed to com.minamp.bc (Minamp's tools/setup_toolchain.sh)
|
||||
OUT=build
|
||||
|
||||
rm -rf "$OUT"
|
||||
mkdir -p "$OUT/gen" "$OUT/classes"
|
||||
|
||||
echo "== resources"
|
||||
aapt package -f -m -J "$OUT/gen" -M AndroidManifest.xml -S res -A assets -I "$ANDROID_JAR" \
|
||||
-F "$OUT/Podlite.unsigned.apk"
|
||||
|
||||
echo "== compile (Java 8 bytecode, API 8 class library)"
|
||||
javac -nowarn -Xlint:-options -encoding UTF-8 -source 8 -target 8 \
|
||||
-bootclasspath "$ANDROID_JAR" -classpath "$ANDROID_JAR" -sourcepath "src:$BC_SRC:$OUT/gen" \
|
||||
-d "$OUT/classes" $(find src "$OUT/gen" -name '*.java')
|
||||
|
||||
echo "== dex"
|
||||
dalvik-exchange --dex --min-sdk-version=8 --output="$OUT/classes.dex" "$OUT/classes"
|
||||
(cd "$OUT" && aapt add Podlite.unsigned.apk classes.dex > /dev/null)
|
||||
|
||||
echo "== align + sign (v1 JAR signature with SHA-1, which Android 2.x requires)"
|
||||
if [ ! -f "$KEYSTORE" ]; then
|
||||
keytool -genkeypair -keystore "$KEYSTORE" -storepass miniabs -keypass miniabs -alias miniabs \
|
||||
-keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Podlite" > /dev/null 2>&1
|
||||
T=${TOOLS:-$HOME/android-toolchain}
|
||||
BC_SRC=$T/bcsrc # Bouncy Castle renamed to com.minamp.bc
|
||||
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
|
||||
KS=${KEYSTORE:-miniabs.keystore} # JKS, password and alias "miniabs": keep it, updates only install over the same key
|
||||
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
|
||||
zipalign -f 4 "$OUT/Podlite.unsigned.apk" "$OUT/Podlite.aligned.apk"
|
||||
apksigner sign --ks "$KEYSTORE" --ks-pass pass:miniabs --key-pass pass:miniabs --ks-key-alias miniabs \
|
||||
--min-sdk-version 8 --v1-signing-enabled true --v2-signing-enabled false --v3-signing-enabled false \
|
||||
--out "$OUT/Podlite.apk" "$OUT/Podlite.aligned.apk"
|
||||
apksigner verify --min-sdk-version 8 "$OUT/Podlite.apk"
|
||||
ls -l "$OUT/Podlite.apk"
|
||||
|
||||
mkdir -p build
|
||||
# signapk.py reads PKCS#12: convert the JKS key into build/ for this run (the original stays as it is)
|
||||
P12=build/signing.p12
|
||||
rm -f $P12
|
||||
keytool -importkeystore -srckeystore "$KS" -srcstoretype JKS -srcstorepass ${KEYPASS:-miniabs} -srcalias miniabs \
|
||||
-destkeystore $P12 -deststoretype PKCS12 -deststorepass ${KEYPASS:-miniabs} -destkeypass ${KEYPASS:-miniabs} \
|
||||
-noprompt >/dev/null 2>&1
|
||||
trap 'rm -f build/signing.p12' EXIT
|
||||
|
||||
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/Podlite.apk ;;
|
||||
16) TARGET=16; APK=build/Podlite-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
|
||||
|
||||
# this level's manifest; Android 3.2+ also counts a rotation as a screen size change; Holo settings on 4.1
|
||||
sed -e "s/android:minSdkVersion=\"[0-9]*\"/android:minSdkVersion=\"$API\"/" \
|
||||
-e "s/android:targetSdkVersion=\"[0-9]*\"/android:targetSdkVersion=\"$TARGET\"/" \
|
||||
$( [ $API -ge 13 ] && echo '-e s/keyboardHidden|orientation"/keyboardHidden|orientation|screenSize"/' ) \
|
||||
$( [ $API -ge 14 ] && echo '-e s#android:theme="@android:style/Theme"#android:theme="@android:style/Theme.Holo"#' ) \
|
||||
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/miniabs/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 -E '^Picked up|META-INF' || 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)
|
||||
$PY tools/signapk.py $P12 ${KEYPASS:-miniabs} $OUT/unsigned.apk $APK
|
||||
python3 tools/check_dex.py $APK
|
||||
ls -l $APK
|
||||
done
|
||||
Reference in new issue
Block a user