I'm trying to integrate Kommunicate Web SDK into my Flutter app, but facing issues with dynamic iframe creation specifically on Android.
I do like this
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
InAppWebView(
onWebViewCreated: (InAppWebViewController controller) {
_controller = controller;
_loadHtmlTemplate();
},
....
Future<void> _loadHtmlTemplate() async {
try {
String htmlTemplate = await rootBundle.loadString('assets/html/template.html');
final chatContent = htmlTemplate.replaceAll('__APP_ID__', widget.token);
await _loadHtmlContent(chatContent);
} catch (e) {
debugPrint('⚠️ Failed to load HTML template: $e');
}
}
Future<void> _loadHtmlContent(String content) async {
await _controller.loadData(
data: content,
mimeType: 'text/html',
encoding: 'utf8',
);
}
Inside template.html
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
(function(d, m){
var kommunicateSettings = {
"appId": "__APP_ID__",
"onInit": function() { }
};
var s = document.createElement("script");
s.type = "text/javascript";
s.async = true;
s.src = "https://widget.kommunicate.io/v2/kommunicate.app";
var h = document.getElementsByTagName("head")[0];
h.appendChild(s);
window.kommunicate = m;
m._globals = kommunicateSettings;
})(document, window.kommunicate || {});
</script>
</head>
<body>
<div class="container">
<div class="loader-overlay" id="loader-overlay">
<p style="margin-bottom: 12px;">Loading…</p>
<div class="loader"></div>
</div>
</div>
</body>
</html>
So as you can see Immediately Invoke Function Expression which finally causing iframe to be loaded and appeared. Everything according the documentation (https://github.com/Kommunicate-io/Kommunicate-Web-SDK), the integration should work with this script inside html's head:
<script type="text/javascript">
(function(d, m){
var kommunicateSettings = {
"appId": "<APP_ID>",
"automaticChatOpenOnNavigation": true,
"popupWidget": true
};
var s = document.createElement("script");
s.type = "text/javascript";
s.async = true;
s.src = "https://widget.kommunicate.io/v2/kommunicate.app";
var h = document.getElementsByTagName("head")[0];
h.appendChild(s);
window.kommunicate = m;
m._globals = kommunicateSettings;
})(document, window.kommunicate || {});
</script>
The problem: both WebView and InAppWebView (using webviewflutter and flutterinappwebview) fail to load the dynamically created iframe on Android, while everything works perfectly on iOS.
On Android, I get errors like "Kommunicate is not defined" because the iframe creation seems to be blocked. I've tried all possible configurations:
InAppWebView(
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
supportMultipleWindows: true,
mixedContentMode: MixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW,
iframeAllowFullscreen: true,
iframeAllow: "microphone; geolocation; camera; autoplay; display-capture",
allowFileAccessFromFileURLs: true,
allowUniversalAccessFromFileURLs: true,
domStorageEnabled: true,
databaseEnabled: true,
mediaPlaybackRequiresUserGesture: false,
allowsInlineMediaPlayback: true,
allowsAirPlayForMediaPlayback: true,
useWideViewPort: true,
loadWithOverviewMode: true,
builtInZoomControls: false,
displayZoomControls: false,
),
onLoadStop: (controller, url) async {
await controller.evaluateJavascript(source: """
document.addEventListener('DOMContentLoaded', function() {
try {
var iframes = document.querySelectorAll('iframe');
iframes.forEach(function(iframe) {
iframe.setAttribute('allow', 'microphone; camera; geolocation; autoplay');
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-downloads');
});
} catch(e) {
console.log('Iframe setup error: ' + e);
}
});
""");
},
)
Nothing helps - it feels like there are some security restrictions on Android that prevent dynamic iframe creation. Has anyone faced and solved this issue with Kommunicate or similar Web SDKs on Android WebView?
Full text:
Top comments (0)