Documentation

Integration Basics

WebView and iframe

Integration to the website via iframe

The room is integrated with the Partner website via iFrame.

Example of a code:


<iframe 
   src="https://chat.watchers.io/?roomId=[Room's ID]&
userId=[User's ID]&apikey=[Partner's API Key]" 
  frameborder="0"
  allow="clipboard-read; clipboard-write; microphone;">
</iframe>

Before the transmission, all get-parameters must be coded via 
encodeURIComponent or its analog.

Integrating a WebView into a Native Application

The room is integrated into the Partner iOS and Android apps via WebView or iFrame for Web Apps.

For each broadcast, its room is initiated. A chat page is generated when the room is opened based on the parameters transmitted. When the first user logs in, the partner passes the event ID using the GET parameter in the link that opens the Webview page. Permit the integrated solution to work with the clipboard.

Example SWIFT code for iOS

import SwiftUI
import WebKit

struct SwiftUIWebView: UIViewRepresentable {
    
    let url: URL?

    func makeUIView (context: Context) -> WKWebView {
        let prefs = WKWebpagePreferences()
        prefs.allowsContentJavaScript = true
        let config = WKWebViewConfiguration()
        config.defaultWebpagePreferences = prefs
        return WKWebView(
            frame: .zero,
            configuration: config
        )
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        guard let myURL = url else {
            return
        }
        let request = URLRequest(url: myURL)
        uiView.load(request)
    }
}

Example Java code for Android

For WebView to function properly, at least two parameters are required:

  • setJavaScriptEnabled must be set to true;
  • setDomStorageEnabled must be set to true.
package com.app.watchers;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.JavascriptInterface;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.MediaController;
import android.widget.VideoView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {
    private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 101;
    private PermissionRequest myRequest;

    WebView web;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        VideoView videoView = findViewById(R.id.videoView);
        videoView.setVideoPath("android.resource://"+getPackageName()+"/"+R.raw.stalker2);
        MediaController mediaController = new MediaController(this);
        mediaController.setAnchorView(videoView);
        videoView.setMediaController(mediaController);

        web = findViewById(R.id.webView);
        WebSettings webSettings = web.getSettings();

        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);

        web.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onPermissionRequest(final PermissionRequest request) {
                myRequest = request;

                for (String permission : request.getResources()) {
                    switch (permission) {
                        case "android.webkit.resource.AUDIO_CAPTURE": {
                            askForPermission(request.getOrigin().toString(), Manifest.permission.RECORD_AUDIO, MY_PERMISSIONS_REQUEST_RECORD_AUDIO);
                            break;
                        }
                    }
                }
            }
        });

        web.setWebViewClient(new Callback());
        web.addJavascriptInterface(new JavaScriptShareInterface(), "AndroidShareHandler");
        web.loadUrl("https://web.dev.watchers.io/?userId=android110420221500&roomId=110420221500");
    }

    private static class Callback extends WebViewClient {
        @Override
        public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
            return false;
        }
    }

    public void askForPermission(String origin, String permission, int requestCode) {
        Log.d("WebView", "inside askForPermission for" + origin + "with" + permission);
        if (ContextCompat.checkSelfPermission(getApplicationContext(), permission) != PackageManager.PERMISSION_GRANTED) {
            // Should we show an explanation?
            if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
            }
        } else {
            myRequest.grant(myRequest.getResources());
        }
    }

    public class JavaScriptShareInterface {
        @JavascriptInterface
        public void share(String url) {
            // your share action
        }
    }
}

💡 It’s required to initialise iframe/webview after user clicks a chat button. Placing an iframe/webview hidden on the page until the first click will promote is an undesirable implementation of integration mechanics.