El provider decide qué MainActivity y qué stack de renderizado recibe tu app. Se elige en el paso Aplicación, en la tarjeta de proveedor, o con el campo provider de la API. El valor se guarda en provider.json dentro del ZIP y el workflow lo lee en el paso Apply provider WebView (pro).
Antes que la tabla de estados, la idea que conviene tener clara: hay tres familias. capacitor, native, twa y gecko (y los alias react-native/ionic) compilan todos el mismo proyecto Gradle: el workflow añade la plataforma Android de Capacitor y ejecuta Gradle; lo único que cambia es si el provider sustituye MainActivity. cordova trae su propio proyecto y su propio job (cordova-build) con la toolchain real de Cordova. flutter y tauri también traen su proyecto y su job: Flutter no toca Gradle de Capacitor y Tauri compila con Cargo en Windows.
| Provider | Qué genera hoy | Compila en CI | Ideal para |
|---|---|---|---|
| Capacitor (default) | Proyecto Capacitor completo: MainActivity extends BridgeActivity, plugins npm, InteeBridge, Ads config |
APK + AAB | Control total con el ecosistema npm |
| Native WebView | MainActivity Java horneada: WebView, permisos runtime, RadioService, AudioBridge, DownloadManager, file chooser |
APK | APK ligero y arranque rápido, sin dependencias |
| GeckoView | MainActivity con GeckoView + PermissionDelegate, file prompt, descargas (onExternalResponse) y patch Gradle Mozilla |
APK | Motor Mozilla puro, aislamiento de Chromium |
| TWA | twa-manifest.json + assetlinks.json (APK sigue siendo la ruta WebView) |
APK | PWA con Digital Asset Links |
| Cordova | config.xml real (SDK, orientación, fullscreen) + plataforma cordova-android en CI |
APK (+AAB) (cordova-build) |
vivir en la toolchain Cordova |
| Flutter | Proyecto Flutter: pubspec.yaml, main.dart, assets, manifiesto propio |
APK + AAB (flutter-build) |
si tu app ya vive en Flutter |
| Tauri | tauri/src-tauri (Rust): Cargo.toml, tauri.conf.json, main.rs, iconos |
EXE de escritorio (tauri-build) |
apps de escritorio con WebView2 |
No están implementados a propósito: NativeScript (otro runtime completo que mantener) y webapkify (solo sirve de referencia: no compila). El "WebToApp propio" del plan es justamente el provider native. TWA no corre bubblewrap en CI: sólo entrega los manifiestos.
capacitor(por defecto) — genera el proyecto Capacitor completo:capacitor.config.json, dependencias@capacitor/*,MainActivity extends BridgeActivity. Es el único con todos los parches probados: permisos runtime, accesos especiales, DownloadManager, audio nativo, Droncito Pack.native— generanative-MainActivity.java(unaAppCompatActivityconWebView, concesión selectiva de permisos, arranque deRadioServiceyAudioBridgehorneados,DownloadListenerque encola enDownloadManager—conibFileName()desdeContent-Dispositiono la URL, y fallback aACTION_VIEW— yonShowFileChooserque abreACTION_GET_CONTENTconEXTRA_MIME_TYPES/EXTRA_ALLOW_MULTIPLEy devuelve losUriporonActivityResultconValueCallback) y el workflow lo copia comoMainActivity.java. Salida ligera y arranque rápido, a cambio de no tener el runtime de Capacitor: los plugins npm no existen yinteebridge.jssólo funciona en los métodos con fallback web (share,vibrate,clipboard,storage,toast,dialog); los que dependen de un plugin (Intee.location(),Intee.camera(),Intee.notifications.schedule()) rechazan con "no disponible".InteeAudiosí funciona, porque el puente nativo está inyectado en la propia clase. Las descargas se pueden desactivar condownloadManager: falseen la config.gecko— generagecko-MainActivity.java(unaAppCompatActivityque crea unGeckoView, abre la URL y hornea los permisos con unPermissionDelegatede GeckoView: pide los permisos Android con código 4101 y devuelvegrant/rejecta la sesión, más el arranque deRadioServicesi hayforeground) ypatch-gecko-gradle.js, que inyecta la dependenciaorg.mozilla.geckoview:geckoviewy el repositoriohttps://maven.mozilla.org/maven2en losbuild.gradle. El workflow lo aplica en el pasoApply GeckoView dependencies, así que compila sin tocar nada a mano. El APK usa el runtime de permisos de Capacitor para todo lo demás. El file chooser pasa porPromptDelegate.onFilePrompt(devuelve unGeckoResult<PromptResponse>y lo resuelve desdeonActivityResultconFilePrompt.confirm(Context, Uri[])oFilePrompt.dismiss()), y las descargas porContentDelegate.onExternalResponse: primero intentaDownloadManagerconContent-Disposition/URL y, si la URL no es re-descargable, copia elbodya Descargas en un hilo. Limitación conocida: GeckoView no exponeaddJavascriptInterface, así que no existewindow.InteeAudioni el puenteIntee.*bajo este provider (el runtime de traspaso decatalog.jslo detecta y se queda sin hacer nada: con pantalla apagada el audio de la WebView se corta). El AAR de GeckoView pesa ~200 MB, la descarga es lenta y ocurre en cada build.twa— generatwa-manifest.jsonyassetlinks.jsonpara que construyas la Trusted Web Activity con bubblewrap (el README incluido lo indica:bubblewrap build --manifest=twa-manifest.json). El APK que compila el workflow sigue siendo la app WebView normal con runtime Capacitor; no es una TWA. Además, la huellasha256_cert_fingerprintsdelassetlinks.jsonse genera con ceros de relleno: hay que sustituirla por la huella real de tu certificado de firma antes de subirla a/.well-known/.cordova— escribe unconfig.xmlreal en la raíz del ZIP (<content src>,access/allow-intent,Orientation,Fullscreen,BackgroundColory las preferencesandroid-minSdkVersion/android-targetSdkVersion/android-compileSdkVersioncon tus versiones) y en CI corre el jobcordova-build:cordova platform add android, inyección de los<uses-permission>/<uses-feature>demain-manifest.xmlen el manifiesto generado (másINTERNETyusesCleartextTrafficsi aplica), icono copiado a losmipmap-*, ycordova build android(APK debug; AAB si lo pediste, concontinue-on-error; release firmado con tu keystore víabuild.json). El jobcompilede Capacitor se salta con este provider. Lo que no hereda: el runtime batchNativePermissions,SpecialAccess,RadioService/AudioBridgeniInteeBridge(la web corre en laCordovaWebViewestándar); en iOS la compilación sigue por Capacitor. El Audit lo trata comoCI_ANDROID(compila APK en CI, permisos por runtime de la app).flutter— escribeflutter/pubspec.yaml(webview_flutter 4 + permission_handler),flutter/lib/main.dart(WebView conloadFlutterAsset('assets/www/index.html')oloadRequestpara URL, controlador inicializado eninitState), unAndroidManifest.xmlpropio sinpackage=(AGP 8 usa elnamespacedel Gradle del scaffold),flutter/assets/www/*con tu web y un README. En CI el jobflutter-buildejecutaflutter createpara generar el host Android, copia tu manifiesto encima, ajustaapplicationId/namespacea tu paquete, mueveMainActivity.ktal paquete correcto y compila: artefactos-apky (si pedisteaab)-aab. El jobcompilede Capacitor se salta con este provider.tauri— escribetauri/src-tauri/Cargo.toml,tauri/src-tauri/build.rs,tauri/src-tauri/tauri.conf.json(distDir: ../../www, CSP conunsafe-inlinepara los scripts inyectados),tauri/src-tauri/src/main.rs, iconos (icons/*.png,icon.ico,icon.icnsfabricados a partir de tu PNG; si tu icono no es PNG se omite la clavebundle.icon) y un README. En CI el jobtauri-buildcorrecargo build --releaseenwindows-latesty sube el artefacto-exe. El proyecto Electron (desktop/) queda desactivado con este provider para no pisarse el artefacto.exe; el APK Android que sale del jobcompilesigue siendo el de Capacitor.react-nativeeionic— son valores válidos ennormalizeConfig, pero no generan nada propio: sólo quedaprovider.jsoncon ese nombre, y el workflow los compila como si fueran Capacitor. No aparecen en el estudio.
Los switches del estudio marcan capacitor, native, twa, gecko, cordova, flutter y tauri en READY (los siete compilan en CI); react-native e ionic no aparecen.
Por API:
curl -X POST /api/build -H "Content-Type: application/json" \
-d '{"appName":"Mi App","url":"https://mi-web.com","provider":"native"}'El ZIP siempre trae provider.json:
{ "provider": "native", "version": "7", "webview": "Native WebView" }Capacitor trae el puente completo (Capacitor, plugins npm, BridgeActivity) y por eso soporta todo el catálogo de plugins y InteeBridge. El provider nativo cambia tres cosas: el MainActivity es una clase propia que carga la URL o file:///android_asset/public/index.html, los permisos runtime y los accesos especiales se invocan directamente desde esa clase, y los plugins npm de Capacitor no existen.
Si vienes de capacitor y cambias a native, revisa el Audit de nuevo: cada permiso cuyo providerOk no incluya el provider nuevo pasa a WARN (los que no declaran esa lista siguen en OK), y eso hace bajar el readiness aunque no bloquee la build.
El Audit añade una columna provider por fila:
OK (<provider>)— el provider está enREADYy el permiso tiene implementación declarada para su runtime.WARN (<provider> sin handler declarado para este permiso)— el provider está enREADYpero ese permiso no declara handler para su runtime (el APK compila igualmente).WARN (<provider> compila APK en CI, permisos por runtime de la app)— paraflutter,tauri,react-native,ionicycordova: el APK se arma por la ruta indicada y los permisos los gestiona el runtime correspondiente.
Un ejemplo concreto de por qué importa: NFC con NDEFReader funciona en Chromium (Capacitor y Native) pero en Gecko el Audit devuelve WARN.
El generador emite configuración, no integración. Si marcas ads y rellenas admobAppId, el ZIP incluye admob-config.json, el manifiesto lleva el meta-data APPLICATION_ID, y normalizeConfig activa el plugin @capacitor-community/admob.
Lo que no se genera: inicialización de MobileAds, AdView, ni código de interstitial ni de rewarded. El Audit lo devuelve explícitamente como NO GENERADO (requiere AdMob App ID + SDK, no incluido) y lo trata como fail, así que un build con ads marcado queda bloqueado hasta que exista la implementación.
assetlinks.json se genera siempre que hay un dominio (campo twaDomain, dominio de deep links o el hostname de tu URL) y se copia también a .well-known/assetlinks.json. Sirve tanto para App Links como para TWA. Recuerda lo dicho arriba: la huella de certificado que trae es de relleno.
Más sobre lo que la app generada expone en security.md; sobre lo que compila realmente, en outputs.md.