Cuatro arreglos del envoltorio, todos vistos al probarlo en el emulador: - onShowFileChooser: sin el, el navegador interno no abre nada al pulsar "Choose File", asi que no se podia subir ninguna imagen. El APK oficial si lo implementa; era una regresion frente a el. - La marca de re-extraccion del backend era el versionName. Al reconstruir la APK sin subir version, la app se quedaba con el backend anterior y ningun cambio se aplicaba. Pasa a ser lastUpdateTime del paquete, que cambia en cada instalacion. (openFd sobre el asset no vale: va comprimido dentro del APK y no admite descriptor.) - La espera del backend sondeaba con HEAD, que el backend rechaza con 400. Ahora abre un socket TCP contra 127.0.0.1:3000, que es lo unico que hay que saber, y espera hasta cinco minutos en vez de uno: descomprimir 231 MB y levantar SSB tarda mas en un movil lento. Mientras, pinta una pantalla de estado con los segundos transcurridos, en vez de dejar el WebView en blanco. - targetUrl/onNewIntent para poder abrir una ruta concreta desde un intent. network_security_config.xml tenia base-config detras de domain-config, que el esquema no admite. Corregido el orden y restaurada la referencia en el manifiesto, que se habia sustituido por usesCleartextTraffic=true al depurar: eso abria texto en claro hacia cualquier host, no solo hacia loopback. |
||
|---|---|---|
| .. | ||
| app | ||
| gradle/wrapper | ||
| scripts | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
Wrapper Android propio
Proyecto Gradle para construir la APK de la rama sin depender del APK oficial como molde.
Por que existe
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
Android deniega por defecto toda peticion de getUserMedia(), de modo que las
videollamadas de Karvan no pueden funcionar por mucho que se parchee el manifest:
la lista de permisos es estatica y hay que declararla al compilar.
Este wrapper resuelve las dos puertas: declara los permisos y los concede al contenido web solo tras el consentimiento del usuario.
Permisos: declarados, no concedidos
CAMERA, RECORD_AUDIO y MODIFY_AUDIO_SETTINGS figuran en el manifest porque
Android exige que la lista sea fija. Pero son permisos peligrosos: se piden en
tiempo de ejecucion la primera vez que se pulsa Llamar, no al instalar. Si nadie
llama, no se pide nada y la app no accede a la camara ni al microfono.
uses-feature ... required="false" evita excluir de la tienda a dispositivos sin
camara o sin microfono.
Que reutiliza y que es nuevo
Las tres librerias nativas se toman tal cual del APK existente:
libnode.so— nodejs-mobile v18.20.4 oficial (OpenSSL 3.0.13+quic), un artefacto publico; no hay que compilar Node.libnative-lib.so— 6,8 KB, un solo simbolo JNI:Java_com_solarnethub_oasis_OasisActivity_startNodeWithArguments.libc++_shared.so
Por eso el namespace del modulo es com.solarnethub.oasis: JNI resuelve por
nombre y la clase puente tiene que vivir en ese paquete. El applicationId si es
propio (net.laenre.oasis), asi que la app se instala junto a la oficial sin
pisarla.
Si algun dia se quiere soltar el .so de epsylon, reimplementar esos 6,8 KB son
unas 40 lineas de C++ contra las cabeceras de nodejs-mobile, y ahi si haria falta
el NDK.
Mejoras sobre el APK actual
targetSdk 35(el actual se quedo en uno ya caducado para la tienda).- Trafico en claro permitido solo hacia loopback via
network_security_config, en vez deusesCleartextTraffic="true"global. allowBackup="false":adb backupdeja de poder extraer~/.ssb.- El backend corre en un servicio en primer plano, en el proceso
:node, asi que sobrevive en segundo plano — imprescindible para recibir llamadas. El APK actual declaraFOREGROUND_SERVICEpero no registra ningun servicio. - Al descomprimir el backend se descartan las entradas con rutas sospechosas (zip slip).
Construir
# 1. dependencias del backend (una vez)
(cd ../src/server && npm install)
# 2. librerias nativas + empaquetado del backend
./scripts/prepare.sh ../../oasis_mobile # o la ruta de un APK
# 3. compilar
./gradlew assembleDebug # o assembleRelease
Para firmar la release, por entorno (la keystore nunca al repositorio):
export OASIS_KEYSTORE=/ruta/oasis-alfa-key.jks
export OASIS_KEYSTORE_PASS=...
export OASIS_KEY_ALIAS=oasis
./gradlew assembleRelease
Requisitos
JDK 17 o superior con compilador. El OpenJDK del sistema puede ser solo
runtime; gradle.properties apunta al JDK que trae Android Studio. Cambia esa
linea si compilas en otra maquina.
Estado
Compila y genera APK con los permisos y el onPermissionRequest en su sitio.
Falta probarlo en un dispositivo real: que arranque el backend, que la
interfaz cargue y que getUserMedia resuelva al pulsar Llamar.