El icono es la isla de la app oficial; antes el lanzador la encogia dentro de un circulo blanco (la oficial solo trae el PNG cuadrado) y el wrapper Gradle usaba un hexagono amarillo. Ahora capa de fondo y capa delante, en Gradle y en sobre_oficial.sh. La app oficial solo vuelve a extraer nodejs-project.zip si cambia versionName.versionCode. Con el mismo commit, o con cambios sin commitear, la APK nueva arrancaba con el backend anterior. El versionName lleva ahora una huella del codigo.
143 lines
6.9 KiB
Bash
Executable file
143 lines
6.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Construye la APK de la rama encima de la APK oficial del dev.
|
|
#
|
|
# Desde la 1.3.x la app Android de epsylon trae cosas que la nuestra no tiene: el
|
|
# puente nativo de audio y camara (.audio_bridge) que usan el Telefono y las Salas,
|
|
# las notificaciones de llamada y sus permisos. Su codigo no esta publicado, asi que
|
|
# en vez de imitarlo se parte de su APK:
|
|
#
|
|
# 1. se baja la APK oficial de la misma version (github, epsylon/oasis)
|
|
# 2. se desmonta con apktool
|
|
# 3. su backend (assets/nodejs-project.zip) se cambia por el de la rama, conservando
|
|
# su node_modules, que es el podado para el movil
|
|
# 4. se le cambia el paquete a net.laenre.oasis (y lo que depende de el) para que
|
|
# conviva con la oficial
|
|
# 5. se vuelve a montar, se alinea y se firma
|
|
#
|
|
# Uso:
|
|
# ./scripts/sobre_oficial.sh # firma con la clave de depuracion
|
|
# OASIS_KEYSTORE=... OASIS_KEYSTORE_PASS=... OASIS_KEY_ALIAS=... ./scripts/sobre_oficial.sh
|
|
#
|
|
# Variables:
|
|
# OASIS_VERSION version del dev (por defecto la de package.json)
|
|
# OASIS_APK_OFICIAL ruta a la APK oficial, si ya se tiene (si no, se baja)
|
|
# ANDROID_HOME por defecto ~/Android/Sdk
|
|
# JAVA_HOME un JDK 17 o superior
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
|
REPO="$(cd "$HERE/.." && pwd)"
|
|
SDK="${ANDROID_HOME:-$HOME/Android/Sdk}"
|
|
JAVA="${JAVA_HOME:+$JAVA_HOME/bin/}java"
|
|
TOOLS="$HERE/.tools"
|
|
OUT="$HERE/build/sobre-oficial"
|
|
PKG_DEV="com.solarnethub.oasis"
|
|
PKG="net.laenre.oasis"
|
|
APKTOOL_VER="3.0.3"
|
|
APKTOOL_SHA="dbf930b076c6b9be08d57c449cacefc3bdd6b71ebd59b3066fc0e1f5b14f9423"
|
|
|
|
say() { printf '\n== %s\n' "$*"; }
|
|
die() { printf '\n!! %s\n' "$*" >&2; exit 1; }
|
|
|
|
VERSION="${OASIS_VERSION:-$(node -p "require('$REPO/package.json').version")}"
|
|
BT="$(ls -d "$SDK"/build-tools/*/ | sort -V | tail -1)"
|
|
[ -x "$BT/zipalign" ] || die "no encuentro zipalign en $BT"
|
|
mkdir -p "$TOOLS" "$OUT"
|
|
|
|
# --- apktool, version fija y comprobada ---------------------------------------
|
|
APKTOOL="$TOOLS/apktool_$APKTOOL_VER.jar"
|
|
if [ ! -f "$APKTOOL" ]; then
|
|
say "bajando apktool $APKTOOL_VER"
|
|
curl -fsSL -o "$APKTOOL" "https://github.com/iBotPeaches/Apktool/releases/download/v$APKTOOL_VER/apktool_$APKTOOL_VER.jar"
|
|
fi
|
|
echo "$APKTOOL_SHA $APKTOOL" | sha256sum -c --quiet - || die "apktool no coincide con la huella esperada"
|
|
|
|
# --- la APK oficial -------------------------------------------------------------
|
|
OFICIAL="${OASIS_APK_OFICIAL:-$TOOLS/oasis-v$VERSION.apk}"
|
|
if [ ! -f "$OFICIAL" ]; then
|
|
say "bajando la APK oficial $VERSION"
|
|
curl -fsSL -o "$OFICIAL" "https://github.com/epsylon/oasis/releases/download/oasis-android-v$VERSION/oasis-v$VERSION.apk"
|
|
fi
|
|
say "APK oficial: $OFICIAL"
|
|
"$BT/apksigner" verify --print-certs "$OFICIAL" | grep -m2 -E "certificate DN|SHA-256" || die "la APK oficial no verifica"
|
|
|
|
# --- desmontar ------------------------------------------------------------------
|
|
say "desmontando"
|
|
rm -rf "$OUT/dec"
|
|
"$JAVA" -jar "$APKTOOL" d -q -f -o "$OUT/dec" "$OFICIAL"
|
|
DEC="$OUT/dec"
|
|
|
|
# --- backend de la rama, con el node_modules del dev ---------------------------
|
|
say "cambiando el backend por el de la rama"
|
|
work="$(mktemp -d)"
|
|
( cd "$work" && unzip -q "$DEC/assets/nodejs-project.zip" )
|
|
mv "$work/nodejs-project/src/server/node_modules" "$work/_nm"
|
|
rm -rf "$work/nodejs-project/src"
|
|
cp -r "$REPO/src" "$work/nodejs-project/src"
|
|
rm -rf "$work/nodejs-project/src/server/node_modules"
|
|
mv "$work/_nm" "$work/nodejs-project/src/server/node_modules"
|
|
cp "$REPO/main.js" "$REPO/package.json" "$REPO/README.md" "$work/nodejs-project/"
|
|
rm -f "$work/nodejs-project/.phone_state.json"
|
|
rm -f "$DEC/assets/nodejs-project.zip"
|
|
( cd "$work" && zip -q -r "$DEC/assets/nodejs-project.zip" nodejs-project )
|
|
rm -rf "$work"
|
|
|
|
# --- paquete propio, para convivir con la oficial ------------------------------
|
|
# Las clases se quedan como estan (com.solarnethub.oasis.OasisActivity...); cambia
|
|
# el paquete, los authorities, el permiso propio y los nombres de las acciones de
|
|
# llamada, que si no se cruzarian con los de la app oficial.
|
|
say "paquete $PKG"
|
|
sed -i \
|
|
-e "s|package=\"$PKG_DEV\"|package=\"$PKG\"|" \
|
|
-e "s|$PKG_DEV.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION|$PKG.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION|g" \
|
|
-e "s|android:authorities=\"$PKG_DEV.|android:authorities=\"$PKG.|g" \
|
|
"$DEC/AndroidManifest.xml"
|
|
grep -rl "\"$PKG_DEV\.[A-Z_]*\"" "$DEC"/smali* | xargs -r sed -i -E "s|\"$PKG_DEV\.([A-Z_]+)\"|\"$PKG.\1\"|g"
|
|
|
|
# icono: el logo de la oficial, pero adaptativo. La oficial solo trae el PNG cuadrado
|
|
# y en Android 8+ el lanzador lo encoge dentro de un circulo blanco; con la capa de
|
|
# fondo y la de delante (app/src/main/res) la isla llena la forma del lanzador
|
|
say "icono adaptativo"
|
|
RES="$HERE/app/src/main/res"
|
|
mkdir -p "$DEC/res/mipmap-anydpi-v26" "$DEC/res/drawable"
|
|
cp "$RES/mipmap-anydpi-v26/ic_launcher.xml" "$DEC/res/mipmap-anydpi-v26/"
|
|
cp "$RES/drawable/ic_launcher_background.xml" "$DEC/res/drawable/"
|
|
for d in mdpi hdpi xhdpi xxhdpi xxxhdpi; do
|
|
cp "$RES/mipmap-$d/ic_launcher_foreground.png" "$DEC/res/mipmap-$d/"
|
|
done
|
|
|
|
# las de prueba (firmadas con la clave de depuracion) se marcan depurables: asi se
|
|
# puede inspeccionar la WebView desde chrome://inspect. Las de publicar, nunca
|
|
if [ -z "${OASIS_KEYSTORE:-}" ]; then
|
|
sed -i 's|<application |<application android:debuggable="true" |' "$DEC/AndroidManifest.xml"
|
|
fi
|
|
|
|
# version: la del dev por mil mas los commits de la rama, para que suba siempre
|
|
CODE_DEV="$(sed -n 's/^ versionCode: //p' "$DEC/apktool.yml")"
|
|
CODE="$(( CODE_DEV * 1000 + $(git -C "$REPO" rev-list --count HEAD) % 1000 ))"
|
|
# la app oficial solo vuelve a extraer nodejs-project.zip si cambia versionName.versionCode;
|
|
# con el mismo commit (o cambios sin commitear) se quedaba con el backend anterior. La
|
|
# huella del codigo en el nombre hace que cada APK distinta se extraiga de nuevo
|
|
HUELLA="$(cd "$REPO" && find src main.js package.json -type f -not -path '*/node_modules/*' -print0 | sort -z | xargs -0 sha1sum | sha1sum | cut -c1-8)"
|
|
NAME="$VERSION-hacklab.$HUELLA"
|
|
sed -i -e "s/^ versionCode: .*/ versionCode: $CODE/" -e "s/^ versionName: .*/ versionName: $NAME/" "$DEC/apktool.yml"
|
|
say "version $NAME (codigo $CODE)"
|
|
|
|
# --- montar, alinear y firmar --------------------------------------------------
|
|
say "montando"
|
|
"$JAVA" -jar "$APKTOOL" b -q -o "$OUT/sin-firmar.apk" "$DEC"
|
|
"$BT/zipalign" -f -p 4 "$OUT/sin-firmar.apk" "$OUT/alineada.apk"
|
|
FINAL="$OUT/oasis-$VERSION-hacklab.apk"
|
|
if [ -n "${OASIS_KEYSTORE:-}" ]; then
|
|
"$BT/apksigner" sign --ks "$OASIS_KEYSTORE" --ks-pass "env:OASIS_KEYSTORE_PASS" \
|
|
--ks-key-alias "${OASIS_KEY_ALIAS:-oasis}" --out "$FINAL" "$OUT/alineada.apk"
|
|
else
|
|
"$BT/apksigner" sign --ks "$HOME/.android/debug.keystore" --ks-pass pass:android \
|
|
--ks-key-alias androiddebugkey --out "$FINAL" "$OUT/alineada.apk"
|
|
fi
|
|
rm -f "$OUT/sin-firmar.apk" "$OUT/alineada.apk" "$FINAL.idsig"
|
|
"$BT/apksigner" verify "$FINAL" || die "la APK firmada no verifica"
|
|
|
|
say "APK: $FINAL ($(du -h "$FINAL" | cut -f1))"
|
|
echo "sha256: $(sha256sum "$FINAL" | cut -d' ' -f1)"
|