Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

Web (TeaVM/WebGL) 🌐

The most honest page in the section. The web target (module web, WebLauncher) compiles the app to JavaScript via TeaVM and runs it on a WebGL2 <canvas> (backend gdx-teavm). It is not GWT and it is not an embedded webview: it is the app itself running in the browser.

Build and serve

gradlew :web:webBundle       # (alias: dist)

Generates web/build/webapp/ with index.html, web.js, scripts/howler.js, gdx.wasm.js, and assets/ + assets.txt. Serve it locally:

cd web/build/webapp && python -m http.server 8080
# open http://127.0.0.1:8080/index.html

The WebLauncher does new TeaApplication(new Main(true, cmdline), config).

⚠️ What does NOT work (it is a stub)

On the web, PlatformUtilsWeb implements most features as a stub — the call exists but does nothing useful:

Feature Behavior on the web
WebContainer createWebView() returns null
GPS / location stub (no fix)
Bluetooth / radios stub (WirelessState.UNSUPPORTED)
Biometrics AuthResult.ERROR “Not supported”
Voice (TTS/STT) voiceToText → onError
Native maps not supported
Vibration / battery stub
File persistence Device.homeFolder = null

Since crossfly-lib (JNI) is not loaded on WebGL (Main.create() skips the SharedLibraryLoader on the WebGL target), everything that depends on native code falls back to the stubs above.

What DOES work

  • Rendering the full UI (it is the real app on the WebGL2 canvas).
  • Opening an external URL / dialing: PlatformUtils.instance.view(url) / dial(numero) (via Gdx.net.openURI).
  • HTTP with restrictions (CORS; Utils.getRemoteFile returns null on failure).

Mandatory pattern: detect and fall back

if (PlatformUtils.instance.createWebView() != null) {
   // Android/iOS/Desktop: embedded webview
} else {
   PlatformUtils.instance.view(url);   // Web: opens in a new tab
}

And check Device.homeFolder == null before attempting to persist a file on the web.

Best practices

  • Disable/adapt device features on the web (don’t leave buttons that do nothing).
  • Persistence on the web: use whatever is available in your build (don’t count on homeFolder).
  • Test by serving the static bundle locally before hosting.

Common mistakes

  • Assuming WebContainer/GPS/biometrics on the web (they are stubs).
  • Trying Device.homeFolder + "arquivo" on the web (homeFolder is null → NPE).

See also

Was this page helpful?