Skip to main content

JavaScript Bridge API

When an HTML5 application runs inside App Container, the container runtime automatically injects JavaScript bridge interfaces under window.appcontainer. On AVS Touch Panels (AVS-10 / AVS-15), these bridge objects grant web applications direct, zero-latency control over the physical hardware — operating onboard relays, reading digital I/O, driving the multicolor RGB bezel LED bar, rendering hardware-accelerated RTSP video streams, managing SIP intercom calls, and launching auxiliary Android apps without requiring network round-trips or authorization tokens.


🔍 Platform & Hardware Detection​

window.appcontainer.isOem​

A boolean flag that indicates whether the application is running on dedicated AVstudio touch panel hardware (such as AVS-10 or AVS-15) vs. a standard mobile device or emulator.

if (window.appcontainer?.isOem) {
console.log("Running on AVS dedicated hardware touch panel (AVS-10 / AVS-15)");
// Enable touch panel hardware controls (RGB bezel LED, relays, GPIO, serial, etc.)
} else {
console.log("Running on standard mobile device (tablet/phone) or desktop browser");
}

🎥 Native Video Streaming - streamBridge​

The native player overlay interface uses Flutter's native libmpv/FFmpeg engine to render RTSP camera streams directly above the WebView. It provides zero added latency and full hardware video decoding.

Opening a Stream​

window.appcontainer.streamBridge.postMessage(JSON.stringify({
action: 'open',
id: 'cam1', // Unique stream identifier string
url: 'rtsp://192.168.1.10:554/stream',
divId: 'player-div' // DOM element ID acting as video container
}));

Alternatively, position the video overlay using fractional screen coordinates (rect object with values from 0.0 to 1.0):

window.appcontainer.streamBridge.postMessage(JSON.stringify({
action: 'open',
id: 'cam1',
url: 'rtsp://192.168.1.10:554/stream',
rect: { x: 0, y: 0, w: 1, h: 0.5 } // Top half of screen
}));

Resizing / Updating Position​

Track DOM changes with ResizeObserver to ensure the native video overlay stays aligned with HTML layout shifts during scroll or window resize:

const playerDiv = document.getElementById('player-div');
const observer = new ResizeObserver(() => {
window.appcontainer.streamBridge.postMessage(JSON.stringify({
action: 'resize',
id: 'cam1',
divId: 'player-div'
}));
});
observer.observe(playerDiv);

Closing Streams​

// Close a specific stream by ID
window.appcontainer.streamBridge.postMessage(JSON.stringify({
action: 'close',
id: 'cam1'
}));

// Close all active native video streams
window.appcontainer.streamBridge.postMessage(JSON.stringify({
action: 'closeAll'
}));

Mute & Volume Control​

Control audio playback volume and muting per stream (fire-and-forget, no status query API):

// Mute audio
window.appcontainer.streamBridge.postMessage(JSON.stringify({ action: 'mute', id: 'cam1' }));

// Unmute audio
window.appcontainer.streamBridge.postMessage(JSON.stringify({ action: 'unmute', id: 'cam1' }));

// Set volume level (0.0 to 1.0)
window.appcontainer.streamBridge.postMessage(JSON.stringify({ action: 'volume', id: 'cam1', volume: 0.5 }));

💡 Hardware & GPIO Control - gpioBridge​

AVS Touch Panel Hardware Feature

Direct control of physical GPIO pins, onboard high-current relays, and the programmable RGB bezel LED light bar is available on AVS-10 and AVS-15 Touch Panels. On standard consumer mobile devices without physical relays or external GPIO headers, these calls are safely ignored.

LED Strip Control​

Control the bezel RGB status LED strip directly from your web project:

// Turn LED strip ON or OFF
window.appcontainer.gpioBridge.postMessage(JSON.stringify({ action: 'ledOn' }));
window.appcontainer.gpioBridge.postMessage(JSON.stringify({ action: 'ledOff' }));

// Set custom RGB color (red, green, blue values from 0 to 255)
window.appcontainer.gpioBridge.postMessage(JSON.stringify({
action: 'ledColor',
red: 255,
green: 128,
blue: 0
}));

GPIO & Relay Control​

Control physical GPIO pins and relay outputs:

Pin IndexPhysical HardwareType
0IO 1Digital I/O (Read / Write)
1IO 2Digital I/O (Read / Write)
2Relay 1Relay Contact Output (CLOSED / OPEN)
3Relay 2Relay Contact Output (CLOSED / OPEN)
// Write high (1) or low (0) level to a GPIO or Relay pin
window.appcontainer.gpioBridge.postMessage(JSON.stringify({
action: 'write',
pin: 2,
level: 1
}));

// Read digital status from an input pin
window.appcontainer.gpioBridge.postMessage(JSON.stringify({
action: 'read',
pin: 0
}));

📡 Low-Level UDP Transmission​

App Container allows web applications to dispatch raw UDP datagrams directly to local network devices without requiring external WebSocket bridges.

sendUdp(host, port, hex)​

Sends hex-encoded binary data over UDP. Broadcast addresses (e.g., 192.168.1.255 or 255.255.255.255) are automatically handled.

window.appcontainer.sendUdp('192.168.1.255', 502, '010600660001A815')
.then(response => {
console.log("UDP Hex Sent:", response);
// Returns: { status: "ok", host: "192.168.1.255", port: 502, sent: 8 }
})
.catch(error => {
console.error("UDP Send Error:", error);
});

sendUdpRaw(host, port, string)​

Sends a raw text string over UDP as-is:

window.appcontainer.sendUdpRaw('192.168.1.100', 9000, 'PING')
.then(response => {
console.log("UDP Raw Sent:", response);
})
.catch(error => console.error("UDP Error:", error));

📲 Native Android Application Management​

Note: Available on AVstudio touch panel hardware running Android.

Web applications can trigger launch or removal of approved third-party Android packages:

// Launch an installed Android package by package name
window.appcontainer.launchApp('com.example.app');

// Request uninstallation of an Android package
window.appcontainer.uninstallApp('com.example.app');

📞 SIP / Intercom Control - sip​

Note: Supported on Android — both AVstudio touch panels (AVS-10 / AVS-15) and standard Android devices running App Container. Not currently available on iOS.

App Container includes a built-in SIP/intercom engine for peer-to-peer (P2P) calling between panels or mobile devices and registration with an IP PBX server. Hosted web applications can control call sessions, display native video windows over DOM elements, mute microphones, adjust call volume, broadcast paging, and listen to telephony events directly via window.appcontainer.sip:

// Place calls
await window.appcontainer.sip.placeCallToIp('192.168.1.50'); // P2P direct call
await window.appcontainer.sip.placeCallToExtension('101'); // PBX extension call

// Answer, reject or dismiss
await window.appcontainer.sip.answer();
await window.appcontainer.sip.reject(); // sends SIP 486 Busy Here
await window.appcontainer.sip.ignore(); // silently mute ring locally (no response sent)
await window.appcontainer.sip.hangup(); // terminate active call

// Mute / unmute local microphone (WebRTC and legacy calls alike)
await window.appcontainer.sip.setMicMuted(true);
await window.appcontainer.sip.setMicMuted(false);

// Adjust call volume (device-wide, 0 to getStatus().callMaxVolume)
await window.appcontainer.sip.setCallVolume(5);

// Native video window overlays (target: 'remote' or 'local')
window.appcontainer.sip.showVideo({ target: 'remote', divId: 'remote-video' });
window.appcontainer.sip.showVideo({ target: 'local', divId: 'local-video' });
window.appcontainer.sip.resizeVideo({ target: 'remote', divId: 'remote-video' });
window.appcontainer.sip.hideVideo({ target: 'local' }); // or hideVideo({}) for both

// Broadcast paging to all discovered panels (P2P mode)
await window.appcontainer.sip.pageAll();
await window.appcontainer.sip.hangupPageAll();

// Query status snapshot
const status = await window.appcontainer.sip.getStatus();
console.log("Mic muted:", status.micMuted, "Volume:", status.callVolume, "/", status.callMaxVolume);

// Listen to call events
window.appcontainer.sip.on('incomingCall', ({ callId, callerName, isBroadcast, hasVideo }) => {
console.log(`Incoming call from ${callerName} (Video: ${hasVideo})`);
});

window.appcontainer.sip.on('callConnected', ({ callId, direction, hasVideo }) => {
if (hasVideo) {
window.appcontainer.sip.showVideo({ target: 'remote', divId: 'remote-video' });
}
});

👉 For full method signatures, video window positioning, status field schemas, and complete event documentation, see the Intercom / SIP API Guide.


🔄 Lifecycle & Page Navigation Rules​

  • Automatic Stream Cleanup: All active native video overlays opened via streamBridge are automatically closed when navigating between HTML pages or reloading the WebView.
  • Persistence: Hardware states (LED colors, GPIO/Relay settings) persist across page navigations until explicitly modified or reset.