How Do You Use WebMessagePort As An Alternative to addJavascriptInterface()?

后端 未结 4 817
不思量自难忘°
不思量自难忘° 2020-12-10 03:42

Google\'s security guidelines for Android app developers has the following:

WebViews do not use addJavaScriptInterface() with untrusted cont

4条回答
  •  -上瘾入骨i
    2020-12-10 04:11

    Here's a solution using the compat lib: Download Full Solution in Android Studio format

    This example uses an index.html and an index.js file stored in the assets folder.

    Here is the JS:

    const channel = new MessageChannel();
    var nativeJsPortOne = channel.port1;
    var nativeJsPortTwo = channel.port2;
    window.addEventListener('message', function(event) {
        if (event.data != 'capturePort') {
            nativeJsPortOne.postMessage(event.data)
        } else if (event.data == 'capturePort') {
            /* The following three lines form Android class 'WebViewCallBackDemo' capture the port and assign it to nativeJsPortTwo
            var destPort = arrayOf(nativeToJsPorts[1])
            nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
            WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY) */
            if (event.ports[0] != null) {
                nativeJsPortTwo = event.ports[0]
            }
        }
    }, false);
    
    nativeJsPortOne.addEventListener('message', function(event) {
        alert(event.data);
    }, false);
    
    nativeJsPortTwo.addEventListener('message', function(event) {
        alert(event.data);
    }, false);
    nativeJsPortOne.start();
    nativeJsPortTwo.start();
    

    And here is the HTML:

    
    
    
        
        WebView Callback Demo
        
    
    
        

    And finally Here is the native Android code:

    class PostMessageHandler(webView: WebView) {
        private val nativeToJsPorts = WebViewCompat.createWebMessageChannel(webView)
        private var nativeToJs: WebMessagePortCompat.WebMessageCallbackCompat? = null
        init {
            if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE)) {
                nativeToJs = object : WebMessagePortCompat.WebMessageCallbackCompat() {
                    override fun onMessage(port: WebMessagePortCompat, message: WebMessageCompat?) {
                        super.onMessage(port, message)
                        Toast.makeText(webView.context, message!!.data, Toast.LENGTH_SHORT).show()
                    }
                }
            }
            var destPort = arrayOf(nativeToJsPorts[1])
            nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
            WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY)
        }
    }
    

    It is important the the native code be executed from the 'WebViewClient.onPageFinished(webView: WebView, url: String)' callback. See download link above for full details. This project shows postMessage working both ways (Native to JS and JS to Native) Hope this helps.

提交回复
热议问题