Web + Mobile Bridge Guide (Bridge)

"Bridge" on the web and mobile refers to a connection code that helps communicate between web content and native code, especially in web applications including hybrid apps or native modules.

These bridges allow web-based code to access or manipulate native features of mobile devices, such as cameras, GPS, and file systems. This enables you to leverage Web technology to build apps that deliver native-like performance and user experience while increasing code reuse across platforms.


1. iOS Bridge Settings

Project Settings

STEP 1. Create a new project in Xcode.

STEP 2. Create a WKWebView.

Creating a Web Page

Create a simple webpage ('index.html') and add it to your project. As an example, use the following web pages.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS Bridge Example</title>
</head>
<body>

<button onclick="sendMessageToiOS('Hello from Web!')">Send Message to iOS</button>

<script>
    function sendMessageToiOS(message) {
        window.webkit.messageHandlers.bridge.postMessage(message);
    }
</script>

</body>
</html>

WKWebView Settings

Set 'WKWebView' in 'View Controller.swift' to load web pages and prepare communication with JavaScript.

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {
    
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let contentController = WKUserContentController()
        contentController.add(self, name: "bridge")
        
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        webView.configuration.userContentController = contentController
        
        if let url = Bundle.main.url(forResource: "index", withExtension: "html") {
            webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
        }
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "bridge", let messageBody = message.body as? String {
            print("Received message from web: \(messageBody)")
            // 필요한 작업 수행
        }
    }
}

Send a message from the web to iOS

When you click the button on the web page, call the JavaScript function 'sendMessageToiOS()' to send a message to the iOS App. On the iOS side, this message will be received via the 'userContentController(_:ddReceive.

Send messages from iOS to the web

Use the 'valuate JavaScript(_:completionHandler:)' method to call the JavaScript function on a web page in the iOS app.

webView.evaluateJavaScript("alert('Hello from iOS!')", completionHandler: nil)

# 2. Android Bridge 설정

Project Settings

STEP 1. Create a new project using Android Studio

STEP 2. Add permission to use Bridge to AndroidManifest.xml.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

STEP 3. Add 'WebView' to 'activity_main.xml'

 <WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Creating a Web Page

Create the file 'index.html' in the 'assets' folder of the project.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>JS Bridge Example</title>
    </head>
    <body>

        <button onclick="sendMessageToAndroid()">Send Message to Android</button>

        <script>
            function sendMessageToAndroid() {
                AndroidBridge.showMessage("Hello from Web!");
            }
        </script>

    </body>
</html>

WebView Settings

`MainActivity.Set WebView in java' or 'MainActivity.kt'.

class MainActivity extends AppCompatActivity {

    private WebView webView;

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

        webView = findViewById(R.id.webview);

        // JavaScript 활성화
        webView.getSettings().setJavaScriptEnabled(true);

        // JavaScript 인터페이스 추가
        webView.addJavascriptInterface(new WebAppInterface(this), "AndroidBridge");

        // Asset 폴더의 HTML 파일 로드
        webView.loadUrl("file:///android_asset/index.html");
    }

    public class WebAppInterface {
        Context mContext;

        WebAppInterface(Context c) {
            mContext = c;
        }

        @JavascriptInterface
        public void showMessage(String message) {
             // 처리 코드를 여기에 추가
        }
    }
}

MainActivity : AppCompatActivity() {

    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById(R.id.webview)

        // JavaScript 활성화
        webView.settings.javaScriptEnabled = true

        // JavaScript 인터페이스 추가
        webView.addJavascriptInterface(WebAppInterface(this), "AndroidBridge")

        // Asset 폴더의 HTML 파일 로드
        webView.loadUrl("file:///android_asset/index.html")
    }

    class WebAppInterface(private val mContext: Context) {

        @JavascriptInterface
        fun showMessage(message: String) {
             // 처리 코드를 여기에 추가
        }
    }
}

Send a message from the web to Android

When you click a button on the web page, the 'showMessage()' method on Android is called via the 'sendMessageToAndroid()' JavaScript function.

Send messages from Android to Web

Use the 'valuateJavascript()' method to invoke the JavaScript function of a web page through 'WebView'.

webView.evaluateJavascript("alert('Hello from Android!');", null)

3. Player Bridge Interworking Guide (Web → App Communication)

Please code according to the basic guide and apply the code to each platform.

Add Player Bridge

iOS

...
let contentController = WKUserContentController()
contentController.add(self, name: "sauceflexEnter")
contentController.add(self, name: "sauceflexMoveExit")
contentController.add(self, name: "sauceflexMoveLogin")
contentController.add(self, name: "sauceflexMoveProduct")
contentController.add(self, name: "sauceflexMoveBanner")
contentController.add(self, name: "sauceflexOnShare")
contentController.add(self, name: "sauceflexPictureInPicture")
contentController.add(self, name: "sauceflexTokenError")
contentController.add(self, name: "sauceflexWebviewReloading")
contentController.add(self, name: "sauceflexMoveReward")
...

Android

...
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexEnter");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexMoveExit");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexMoveLogin");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexMoveProduct");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexMoveBanner");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexOnShare");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexPictureInPicture");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexTokenError");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexWebviewReloading");
webView.addJavascriptInterface(new WebAppInterface(this), "sauceflexMoveReward");
...
...
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexEnter")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexMoveExit")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexMoveLogin")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexMoveProduct")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexMoveBanner")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexOnShare")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexPictureInPicture")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexTokenError")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexWebviewReloading")
webView.addJavascriptInterface(WebAppInterface(this), "sauceflexMoveReward")
...

Add bridge capabilities to communicate

iOS

extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController,
                                    didReceive message: WKScriptMessage) {
        switch (message.name) {
            case "sauceflexEnter":   // start render
                print("sauceflexEnter")
                break
 
            case "sauceflexMoveExit":   // exit button click 
                print("sauceflexMoveExit")
                break
 
            case "sauceflexMoveLogin":   // login popup
                print("sauceflexMoveLogin")
                break
 
            case "sauceflexMoveProduct":   // product link click
                print("sauceflexMoveProduct")
                print(message.body)
                break
 
            case "sauceflexOnShare":   // Share
                print("sauceflexOnShare")
                print(message.body)
                break
 
            case "sauceflexPictureInPicture":   
            // Click the PIP switch button to automatically process component GONE processing being displayed when switching the PIP view. (Like buttons, etc. shown above the player)
                print("sauceflexPictureInPicture")
                print(message.body)
                break
 
            case "sauceflexMoveBanner":  
            // BannerId (banner unique ID), linkUrl (URL registered in banner) and broadcastIdx (broadcast number) information can be viewed through message.body when clicking on the banner.
                print("sauceflexMoveBanner")
                print(message.body)
                break
            
            case "sauceflexWebviewReloading":   // webviewReload
                print("sauceflexWebviewReloading")
                print(message.body)
                break

            case "sauceflexMoveReward":   // Reward
                print("sauceflexMoveReward")
                print(message.body)
                break
 
            default:
                print("message.name \\(message.name) not handled.")
        }
    }
}

Android

public class AndroidBridge {
    private final Context context;
    private final Handler handler = new Handler();

    public AndroidBridge(Context context) {
        this.context = context;
    }

    // start render
    @JavascriptInterface
    public void sauceflexEnter() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                 // Please add the code here
            }
        });
    }

    //  exit button click 
    @JavascriptInterface
    public void sauceflexMoveExit() {
        handler.post(new Runnable() {
            @Override
            public void run() {
            }
        });
    }

    // login popup
    @JavascriptInterface
    public void sauceflexMoveLogin() {
        handler.post(new Runnable() {
            @Override
            public void run() {
            }
        });
    }

    // product link click
    @JavascriptInterface
    public void sauceflexMoveProduct(String message) {
        final String finalMessage = message;
        handler.post(new Runnable() {
            @Override
            public void run() {
                 // 처리 코드를 여기에 추가
            }
        });
    }

    // Share
    @JavascriptInterface
    public void sauceflexOnShare(String message) {
        final String finalMessage = message;
        handler.post(new Runnable() {
            @Override
            public void run() {
                 // 처리 코드를 여기에 추가
            }
        });
    }

    @JavascriptInterface
    public void sauceflexPictureInPicture() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                 // 처리 코드를 여기에 추가
            }
        });
    }

    // banner click callback to bannerId, linkUrl , broadcastIdx 
    @JavascriptInterface
    public void sauceflexMoveBanner(String message) {
        final String finalMessage = message;
        handler.post(new Runnable() {
            @Override
            public void run() {
            }
        });
    }
    
    @JavascriptInterface
    public void sauceflexWebviewReloading(String message) {
        final String finalMessage = message;
        handler.post(new Runnable() {
            @Override
            public void run() {
            }
        });
    }
    
    @JavascriptInterface
    public void sauceflexMoveReward(String message) {
        final String finalMessage = message;
        handler.post(new Runnable() {
            @Override
            public void run() {
            }
        });
    }    
}
class AndroidBridge(private val context: Context) {
    private val handler = Handler()
  
    @JavascriptInterface   
    fun sauceflexEnter() {
        handler.post {
        }
    }
  
    @JavascriptInterface  
    fun sauceflexMoveExit() {
        handler.post {
        }
    }
  
    @JavascriptInterface   
    fun sauceflexMoveLogin() {
        handler.post {
        }
    }
  
    @JavascriptInterface   
    fun sauceflexMoveProduct(message: String) {
        handler.post {
        }
    }
  
    @JavascriptInterface   
    fun sauceflexOnShare(message: String) {
        handler.post {
        }
    }
  
   @JavascriptInterface  
   fun sauceflexPictureInPicture () {
       handler.post {
       }
    }
 
    @JavascriptInterface  
    fun sauceflexMoveBanner(message: String) {
        handler.post {
        }
    }
    
    @JavascriptInterface 
    fun sauceflexWebviewReloading(message: String) {
        handler.post {
        }
    }
    
    @JavascriptInterface 
    fun sauceflexMoveReward(message: String) {
        handler.post {
        }
    }    
 
}