GrayPause 1.4: grayscale color breaks for Android

Timers that switch grayscale off and restore it on their own: presets and
custom h/m/s timers, Quick Settings tile, launcher shortcuts, countdown
notification, reboot recovery, and optional always-in-color apps via an
accessibility service. WRITE_SECURE_SETTINGS is granted once via Shizuku
or adb.

Gradle project for F-Droid with fastlane metadata and a draft fdroiddata
recipe; build.sh keeps the Gradle-free on-phone Termux build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Loïc Wisniewski 2026-10-04 20:07:49 +02:00
commit 5d7d84eaca
38 changed files with 2419 additions and 1 deletions

59
build.sh Executable file
View file

@ -0,0 +1,59 @@
#!/data/data/com.termux/files/usr/bin/bash
# Gradle-free debug build for Termux on the phone itself: native aapt2/javac/apksigner,
# plus d8 and android.jar borrowed from the Android SDK in the proot Ubuntu container.
# Release/F-Droid builds use Gradle instead (./gradlew assembleRelease).
set -euo pipefail
cd "$(dirname "$0")"
SDK=${ANDROID_SDK:-$PREFIX/var/lib/proot-distro/containers/ubuntu/rootfs/root/android-sdk}
ANDROID_JAR=$SDK/platforms/android-36/android.jar
D8_JAR=$SDK/build-tools/36.1.0/lib/d8.jar
KEYSTORE=$HOME/.android/debug.keystore
MAIN=app/src/main
OUT=build/termux
# Single source of truth for ids and versions is app/build.gradle.
gradle_value() { sed -n "s/^ *$1 *\"\{0,1\}\([^\"]*\)\"\{0,1\} *$/\1/p" app/build.gradle | head -1; }
APP_ID=$(gradle_value applicationId)
VERSION_CODE=$(gradle_value versionCode)
VERSION_NAME=$(gradle_value versionName)
MIN_SDK=$(gradle_value minSdk)
TARGET_SDK=$(gradle_value targetSdk)
SHIZUKU=$(sed -n 's/.*def shizuku = "\(.*\)"/\1/p' app/build.gradle)
rm -rf "$OUT" && mkdir -p "$OUT"/{gen,classes,dex,libs}
# Shizuku client: classes.jar out of each AAR from Maven Central, cached between builds.
CACHE=build/maven-cache/$SHIZUKU && mkdir -p "$CACHE"
for a in api provider aidl shared; do
jar=$CACHE/$a.jar
if [ ! -f "$jar" ]; then
curl -sfL -o "$CACHE/$a.aar" \
"https://repo1.maven.org/maven2/dev/rikka/shizuku/$a/$SHIZUKU/$a-$SHIZUKU.aar"
unzip -p "$CACHE/$a.aar" classes.jar > "$jar"
fi
cp "$jar" "$OUT/libs/"
done
# Gradle injects the package from `namespace`; aapt2 needs it in the manifest itself.
sed "s|<manifest |<manifest package=\"$APP_ID\" |" $MAIN/AndroidManifest.xml > $OUT/AndroidManifest.xml
aapt2 compile --dir $MAIN/res -o $OUT/res.zip
aapt2 link -I "$ANDROID_JAR" --manifest $OUT/AndroidManifest.xml \
--min-sdk-version "$MIN_SDK" --target-sdk-version "$TARGET_SDK" \
--version-code "$VERSION_CODE" --version-name "$VERSION_NAME" \
--java $OUT/gen -o $OUT/unsigned.apk $OUT/res.zip
LIBS=$(ls $OUT/libs/*.jar | paste -sd:)
javac -source 17 -target 17 -nowarn -classpath "$ANDROID_JAR:$LIBS" -d $OUT/classes \
$(find $MAIN/java $OUT/gen -name '*.java')
java -cp "$D8_JAR" com.android.tools.r8.D8 --release --min-api "$MIN_SDK" \
--lib "$ANDROID_JAR" --output $OUT/dex $(find $OUT/classes -name '*.class') $OUT/libs/*.jar
javac -d $OUT tools/ZipAlign.java
java -cp $OUT ZipAlign $OUT/unsigned.apk $OUT/aligned.apk $OUT/dex/classes.dex
apksigner sign --ks "$KEYSTORE" --ks-pass pass:android --key-pass pass:android \
--out GrayPause.apk $OUT/aligned.apk
apksigner verify GrayPause.apk
echo "Built $(pwd)/GrayPause.apk ($APP_ID $VERSION_NAME)"