android: la APK se monta sobre la oficial del dev

La app Android de epsylon trae desde la 1.3.x un puente nativo de audio y
camara (.audio_bridge) para el Telefono y las Salas, y no tiene el codigo
publicado. android/scripts/sobre_oficial.sh coge su APK de la misma version,
le cambia el backend por el de la rama (con su node_modules), le pone el
paquete net.laenre.oasis (y los authorities, el permiso propio y las acciones
de llamada) para que conviva con la oficial, y la monta y firma. apktool va
con version y huella fijas.

Probado en el emulador: el Telefono ofrece llamadas y en una sala el
microfono graba y se corta al salir. README, guia, android/README y los
esquemas lo cuentan; el proyecto Gradle propio queda sin uso.
This commit is contained in:
hacklab 2026-10-19 14:12:18 +02:00
parent 34265c2ed0
commit 6bacafea64
9 changed files with 182 additions and 36 deletions

View file

@ -6,8 +6,9 @@ molde.
## Por que existe
Nota (19/10/2026): desde la 1.3.x la APK oficial ya pide microfono y camara y trae un
puente nativo de audio y camara (`.audio_bridge`) para el Telefono y las Salas. Esta app
aun no lo tiene. Lo de abajo describe la situacion anterior.
puente nativo de audio y camara (`.audio_bridge`) para el Telefono y las Salas. Por eso
la APK de la rama se monta ahora sobre la oficial con `scripts/sobre_oficial.sh`, y el
proyecto Gradle de esta carpeta queda sin uso. Lo de abajo describe la situacion anterior.
El APK que se venia usando es el de epsylon re-firmado, y su `classes.dex` **no
implementa `WebChromeClient.onPermissionRequest`**. Sin ese metodo el WebView de

126
android/scripts/sobre_oficial.sh Executable file
View file

@ -0,0 +1,126 @@
#!/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"
# 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 ))"
sed -i -e "s/^ versionCode: .*/ versionCode: $CODE/" -e "s/^ versionName: .*/ versionName: $VERSION-hacklab/" "$DEC/apktool.yml"
say "version $VERSION-hacklab (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)"