Frontend IntegrationEvents and API

Events and API

Listen to N2I session lifecycle events and call the runtime API from an iframe or WebView.

Events

N2I emits events throughout the session lifecycle. Subscribe to them to react to connection state changes, user interactions, and data from the streamed app.

Event Reference

EventDetail payloadDescription
n2i_connectedThe session has been allocated and the stream is establishing. Use this to show a loading indicator.
n2i_readyThe stream is active and the first frame has been rendered. Use this to reveal the iframe/WebView to the user.
n2i_disconnected{ reason, code }The session has ended. reason: one of api, n2i://close, inactivity, duration, network. code: a WebSocket close code (1000 = normal close, 1006 = abnormal, negative = unknown). Use this to hide the iframe/WebView and show a return-to-menu screen.
n2i_inactivity_timeoutThe session ended because the inactivity timer expired.
n2i_invisibility_timeoutThe session ended because the invisibility timer expired.
n2i_status_data{ downBytes, upBytes, nbFrames, networkStatus: { downJitterMs, jitterBufferExpMs, jitterBufferMs } }Periodic network and rendering statistics since n2i_connected. Useful for displaying connection quality indicators.
n2i_custom_packet{ type, str, binData }A custom packet was received from the streamed app. type is an integer identifier; str is string data; binData is a Uint8Array.
n2i_open_url_notify<url string>The streamed app opened a URL with an http:, https:, or n2i-send: scheme.
n2i_data{ data: <url>, extras: <object> }The streamed app sent data via the N2I receiver Intent.
n2i_app_start_end<package name>The streamed application was started.

Receiving Events from an iframe

N2I dispatches events to the parent page via the browser's postMessage API. Each message has the shape:

{ type: "<event-type>", detail: <event-detail> }
window.addEventListener("message", (event) => {
  // Always validate the origin
  if (event.origin !== "https://project-xyz.k8s.n2i.io") return;

  const { type, detail } = event.data ?? {};

  switch (type) {
    case "n2i_ready":
      document.getElementById("n2i-iframe").style.visibility = "visible";
      break;

    case "n2i_disconnected":
      console.log("Session ended:", detail.reason, detail.code);
      document.getElementById("n2i-iframe").src = "about:blank";
      break;

    case "n2i_status_data":
      console.log("Frames rendered:", detail.nbFrames);
      break;
  }
});

Receiving Events from a WebView

Register a JavaScript interface on the WebView under the name n2iWebView. N2I will call onEvent for each event.

private class N2iHandler {
    @JavascriptInterface
    public void onEvent(String type, String detail) {
        // detail is a JSON string for events that carry a payload, null otherwise
        Log.d("N2I", "event=" + type + " detail=" + detail);

        runOnUiThread(() -> {
            switch (type) {
                case "n2i_ready":
                    myWebView.setVisibility(View.VISIBLE);
                    break;
                case "n2i_disconnected":
                    // parse detail JSON, then navigate away
                    myWebView.loadUrl("about:blank");
                    break;
            }
        });
    }
}

myWebView.addJavascriptInterface(new N2iHandler(), "n2iWebView");

API

Use the N2I API to control the streaming session programmatically from your client.

API Reference

MethodParametersDescription
connectConnects the streaming session.
disconnectDisconnects the streaming session cleanly.
backSends an Android back-button event to the streamed app.
sendCustomPackettype (integer), data (string or Uint8Array)Sends a custom packet to the streamed app.
sendDeeplinkapp (package name), uri (deeplink URI)Sends a deeplink to the streamed app.
startAppapp (package name), uri (deeplink URI, optional), startIntent (JSON intent, optional)Starts an application on the stream using a deeplink or Intent.

Calling the API from an iframe

Send a postMessage to the iframe's contentWindow:

const iframe = document.getElementById("n2i-iframe");

iframe.contentWindow.postMessage(
  { type: "<method-name>", detail: <parameters> },
  "https://project-xyz.k8s.n2i.io"  // use the exact N2I origin, not "*"
);

Examples:

// Send a custom packet
iframe.contentWindow.postMessage(
  { type: "sendCustomPacket", detail: [0x1234, "Hello from client"] },
  "https://project-xyz.k8s.n2i.io"
);

// Send a deeplink
iframe.contentWindow.postMessage(
  { type: "sendDeeplink", detail: ["com.example.mygame", "mygame://level/5"] },
  "https://project-xyz.k8s.n2i.io"
);

// Disconnect the session
iframe.contentWindow.postMessage(
  { type: "disconnect" },
  "https://project-xyz.k8s.n2i.io"
);

Always specify the exact N2I origin as the targetOrigin argument instead of "*". This prevents your messages from being intercepted by other frames.


Calling the API from a WebView

The n2i JavaScript object is available directly in the WebView context.

Android:

myWebView.loadUrl("javascript:n2i.sendCustomPacket(0x1234, 'Hello from client')");
myWebView.loadUrl("javascript:n2i.sendDeeplink('com.example.mygame', 'mygame://level/5')");
myWebView.loadUrl("javascript:n2i.disconnect()");

iOS:

webView.evaluateJavaScript("n2i.sendCustomPacket(0x1234, 'Hello from client')")
webView.evaluateJavaScript("n2i.disconnect()")