Android与JS交互篇--JSBridge的使用

在android日常开发中,大家或多或少都会碰到原生嵌套web页面,大家可以使用传统的方式实现Native与JS的交互,这里就不多介绍了,现在我们简单介绍下网上目前比较流行的已经封装好的框架JsBridge。

可参考官网github地址:点击打开链接

先看下接下来将要实现的效果图:

一、JsBridge的基本概念
Android4.4以前,谷歌的webview存在安全漏洞,网站可以通过js注入就可以随便拿到客户端的重要信息,甚至轻而易举的调用本地代码进行流氓行为,谷歌在4.4以后增加了防御措施,如果用js调用本地代码,开发者必须在代码声明JavascriptInterface, 4.4之前我们要使得webView加载js只需如下代码:

mWebView.addJavascriptInterface(new JsToJava(), “myfunction”);
4.4之后使用时, 需要在调用Java方法加入@JavascriptInterface注解,如果代码无此声明,那么js就不生效,这样就可以避免恶意网页利用js对客户端的进行窃取和攻击。 但使用比较繁琐,要做一些判断和限制,在比较复杂的Hybrid模式下,需要js和native之间进行交互通讯,原生的JavascriptInterface 难以维护,基于JavascriptInterface 封装的WebViewJavascriptBridge框架,很好的解决了这一问题。

WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,用于替代WebView自带的JavascriptInterface接口,使开发者可以简单安全的实现js和native交互。

二、以上图为案例介绍JSBridge的使用方法
首先在Module的build.gradle里引入JSBridge所需要的包,也可以下载源码引入项目自定义库文件

repositories {
    maven { url "https://jitpack.io" }
}
 
dependencies {
    ...
    compile 'com.github.lzyzsd:jsbridge:1.0.4'
}

在xml文件中使用控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:padding="20dp"
    android:background="#9f9f9f"
    tools:context="com.liuw.jsbridge.MainActivity">
 
    <EditText
        android:id="@+id/edit_view"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ffffff"
        android:gravity="top"
        android:textSize="14sp"
        android:textColor="@color/colorAccent"
        android:text="来自于js将要展示的数据"/>
 
    <Button
        android:id="@+id/btn_send"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:layout_marginTop="10dp"
        android:text="发送数据到webView"/>
 
    <Button
        android:id="@+id/btn_reset"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:layout_marginTop="10dp"
        android:text="重置浏览器"/>
 
    <com.github.lzyzsd.jsbridge.BridgeWebView
        android:id="@+id/bridge_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="20dp">
 
    </com.github.lzyzsd.jsbridge.BridgeWebView>
</LinearLayout>

MainActivity主界面中使用

下面先简单介绍下重点几步操作:

1、加载网页地址
mBridgeWebview.loadUrl("file:///android_asset/web.html");
2、注册handler,接收来自js的数据data,并可通过onCallBack回传数据
mBridgeWebview.registerHandler("submitFromWeb", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                if (!TextUtils.isEmpty(data)) {
                    mEditText.setText("通过调用Native方法接收数据:\n" + data);
                }
                function.onCallBack("Native已经接收到数据:" + data + ",请确认!");
            }
        });
对应的js代码如下

function useClick() {
            var name = document.getElementById("uname").value;
            var pwd = document.getElementById("psw").value;
            var data = "name = " + name + ", password = " + pwd;
 
            window.WebViewJavascriptBridge.callHandler(
                'submitFromWeb', {'info':data},//data发送给native
                function(responseData) {//接收onCallBack回传回来的数据
                    document.getElementById("show").innerHTML = responseData;
                }
            );
     }
上面这种方法是通过native和js定义相同的标识进行通信,还有种方法可直接在js中通过send方法发送,并在native中创建DefaultHandler接收

mBridgeWebview.setDefaultHandler(new DefaultHandler(){
            @Override
            public void handler(String data, CallBackFunction function) {
                function.onCallBack("Native已收到消息!");
            }
        });
对应js代码如下:

//h5直接通过send向Native发送消息,在DefaultHandler的handler方法里接收,并可通过onCallBack方法回传
    function sendClick() {
        var name = document.getElementById("uname").value;
        var pwd = document.getElementById("psw").value;
        var data = "name = " + name + ", password = " + pwd;
 
        window.WebViewJavascriptBridge.send(
            data,
            function(responseData) {
                document.getElementById("show").innerHTML = responseData
            }
        );
    }
3、定义callHandler,多用于在初始化界面时native向js发送数据渲染界面,同时也可获取来自js的数据
mBridgeWebview.callHandler("functionInJs", new Gson().toJson(new UserInfo("liuw", "123456")), new CallBackFunction() {
            @Override
            public void onCallBack(String data) {
                mEditText.setText("向h5发送初始化数据成功,接收h5返回值为:\n" + data);
            }
        });
对应的js代码如下

function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }
 
// 第一连接时初始化bridage
connectWebViewJavascriptBridge(function(bridge) {
            //注册handler等待java代码调用
            //初始化时获取数据是调用此处代码
            //参数:标识,要传递到JAVA的数据,回调方法。
            //JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
            bridge.registerHandler("functionInJs", function(data, responseCallback) {
                document.getElementById("show").innerHTML = ("data from Java: = " + data);
                var responseData = "I am javascript, Data reception success!";
                responseCallback(responseData);
            });
})
4、Native中send方法的使用
这里需要注意下,该方法对应js中的bridge.init处理,此处需加CallBackFunction方法,如果只使用mBridgeWebview.send("");如:mBridgeWebview.send("hello");,会导致js中只收到通知,接收不到值
mBridgeWebview.send("来自java的发送消息!!!", new CallBackFunction() {
            @Override
            public void onCallBack(String data) {
                Toast.makeText(MainActivity.this, "bridge.init初始化数据成功" + data, Toast.LENGTH_SHORT).show();
            }
        });
对应的js代码如下

function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }
 
    // 第一连接时初始化bridage
    connectWebViewJavascriptBridge(function(bridge) {
            //也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                var data = {
                    'Javascript Responds': '测试中文!'
                };
                console.log('JS responding with', data);
                responseCallback(data);
            });
    })
5、再介绍一种常规的Native直接向js传递数据的方法
//直接调用nativeFunction方法向H5发送数据
mBridgeWebview.loadUrl("javascript:nativeFunction('" + data + "')");
对应的js代码如下

    function nativeFunction(data) {
        document.getElementById("show").innerHTML = data;
    }
只需通过方法名直接调用即可,是不是很简单啊~

三、下面上完整代码
package com.liuw.jsbridge;
 
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
 
import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.BridgeWebView;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.github.lzyzsd.jsbridge.DefaultHandler;
import com.google.gson.Gson;
import com.liuw.jsbridge.bean.UserInfo;
 
import butterknife.ButterKnife;
import butterknife.InjectView;
 
public class MainActivity extends AppCompatActivity {
 
    @InjectView(R.id.edit_view)
    EditText mEditText;
    @InjectView(R.id.btn_send)
    Button btnSend;
    @InjectView(R.id.bridge_webview)
    BridgeWebView mBridgeWebview;
    @InjectView(R.id.btn_reset)
    Button btnReset;
 
    private String TAG = "MainActivity";
    private MyHandlerCallBack.OnSendDataListener mOnSendDataListener;
    private ValueCallback<Uri> mUploadMessage;
    ;
    private ValueCallback<Uri[]> mUploadCallbackAboveL;
    private final static int FILECHOOSER_RESULTCODE = 1;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
 
        initListener();
        initWebView();
    }
 
    private void initWebView() {
        //辅助WebView设置处理关于页面跳转,页面请求等操作
        mBridgeWebview.setWebViewClient(new MyWebViewClient(mBridgeWebview, MainActivity.this));
        //Handler做为通信桥梁的作用,接收处理来自H5数据及回传Native数据的处理,当h5调用send()发送消息的时候,调用MyHandlerCallBack
        mBridgeWebview.setDefaultHandler(new MyHandlerCallBack(mOnSendDataListener));
        //WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比等,不过它还能处理文件上传操作
        mBridgeWebview.setWebChromeClient(new MyChromeWebClient());
        // 如果不加这一行,当点击界面链接,跳转到外部时,会出现net::ERR_CACHE_MISS错误
        // 需要在androidManifest.xml文件中声明联网权限
        // <uses-permission android:name="android.permission.INTERNET"/>
        if (Build.VERSION.SDK_INT >= 19) {
            mBridgeWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        }
 
        //加载网页地址
        mBridgeWebview.loadUrl("file:///android_asset/web.html");
 
        //有方法名的都需要注册Handler后使用
        mBridgeWebview.registerHandler("submitFromWeb", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Log.i("liuw", "html返回数据为:" + data);
                if (!TextUtils.isEmpty(data)) {
                    mEditText.setText("通过调用Native方法接收数据:\n" + data);
                }
                function.onCallBack("Native已经接收到数据:" + data + ",请确认!");
            }
        });
 
        mBridgeWebview.registerHandler("functionOpen", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Toast.makeText(MainActivity.this, "网页在打开你的文件预览", Toast.LENGTH_SHORT).show();
            }
        });
 
        //应用启动后初始化数据调用,js处理方法connectWebViewJavascriptBridge(function(bridge)
        mBridgeWebview.callHandler("functionInJs", new Gson().toJson(new UserInfo("liuw", "123456")), new CallBackFunction() {
            @Override
            public void onCallBack(String data) {
                mEditText.setText("向h5发送初始化数据成功,接收h5返回值为:\n" + data);
            }
        });
 
        //对应js中的bridge.init处理,此处需加CallBackFunction,如果只使用mBridgeWebview.send("");会导致js中只收到通知,接收不到值
        mBridgeWebview.send("来自java的发送消息!!!", new CallBackFunction() {
            @Override
            public void onCallBack(String data) {
                Toast.makeText(MainActivity.this, "bridge.init初始化数据成功" + data, Toast.LENGTH_SHORT).show();
            }
        });
 
    }
 
    private void initListener() {
        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String data = mEditText.getText().toString();
                //直接调用nativeFunction方法向H5发送数据
                mBridgeWebview.loadUrl("javascript:nativeFunction('" + data + "')");
            }
        });
 
        btnReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBridgeWebview.loadUrl("file:///android_asset/web.html");
            }
        });
 
        mOnSendDataListener = new MyHandlerCallBack.OnSendDataListener() {
            @Override
            public void sendData(String data) {
                mEditText.setText("通过webview发消息接收到数据:\n" + data);
            }
        };
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILECHOOSER_RESULTCODE) {
            if (null == mUploadMessage && null == mUploadCallbackAboveL) {
                return;
            }
            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
            if (mUploadCallbackAboveL != null) {
                onActivityResultAboveL(requestCode, resultCode, data);
            } else if (mUploadMessage != null) {
                mUploadMessage.onReceiveValue(result);
                mUploadMessage = null;
            }
        }
    }
 
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
        if (requestCode != FILECHOOSER_RESULTCODE
                || mUploadCallbackAboveL == null) {
            return;
        }
 
        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (data == null) {
 
            } else {
                String dataString = data.getDataString();
                ClipData clipData = data.getClipData();
 
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        ClipData.Item item = clipData.getItemAt(i);
                        results[i] = item.getUri();
                    }
                }
 
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
        }
        mUploadCallbackAboveL.onReceiveValue(results);
        mUploadCallbackAboveL = null;
    }
 
    //自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签,点击会自动调用】
    public class MyChromeWebClient extends WebChromeClient {
        // For Android 3.0-
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
        }
 
        // For Android 3.0+
        public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
        }
 
        //For Android 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
        }
 
        // For Android 5.0+会调用此方法
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            Log.d(TAG, "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadCallbackAboveL = filePathCallback;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
            return true;
        }
    }
 
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // 处理返回键,在webview界面,按下返回键,不退出程序
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (mBridgeWebview != null && mBridgeWebview.canGoBack()) {
                mBridgeWebview.goBack();
                return true;
            }else {
                System.exit(0);
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}

自定义MyHandlerCallBack类

package com.liuw.jsbridge;
 
import android.text.TextUtils;
import android.util.Log;
 
import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
 
/**
 * Created by liuw on 2018/3/6.
 * 自定义Handler回调
 */
 
class MyHandlerCallBack implements BridgeHandler {
    private OnSendDataListener mSendDataListener;
 
    public MyHandlerCallBack(OnSendDataListener mSendDataListener){
        this.mSendDataListener = mSendDataListener;
    }
 
    @Override
    public void handler(String data, CallBackFunction function) {
        Log.e("liuw","接收数据为:" + data);
        if (!TextUtils.isEmpty(data) && mSendDataListener != null) {
            mSendDataListener.sendData(data);
        }
        function.onCallBack("Native已收到消息!");
    }
 
    public interface OnSendDataListener {
        void sendData(String data);
    }
}

自定义MyWebViewClient类

package com.liuw.jsbridge;
 
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.webkit.WebView;
 
import com.github.lzyzsd.jsbridge.BridgeWebView;
import com.github.lzyzsd.jsbridge.BridgeWebViewClient;
 
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
 
/**
 * Created by liuw on 2018/3/6.
 * 自定义WebViewClient
 */
 
class MyWebViewClient extends BridgeWebViewClient {
    private Context mContext;
    public MyWebViewClient(BridgeWebView mBridgeWebview, Context context) {
        super(mBridgeWebview);
        mContext = context;
    }
 
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Log.i("liuw", "url地址为:" + url);
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //默认操作url地址yy://__QUEUE_MESSAGE__/
        if (url.trim().startsWith("yy:")) {
            return super.shouldOverrideUrlLoading(view, url);
        }
        //特殊情况tel,调用系统的拨号软件拨号【<a href="tel:110">拨打电话110</a>】
        if(url.trim().startsWith("tel")){
            Intent i = new Intent(Intent.ACTION_VIEW);
            i.setData(Uri.parse(url));
            mContext.startActivity(i);
        }else {
            //特殊情况【调用系统浏览器打开】<a href="https://www.csdn.net">调用系统浏览器</a>
            if(url.contains("csdn")){
                Intent i = new Intent(Intent.ACTION_VIEW);
                i.setData(Uri.parse(url));
                mContext.startActivity(i);
            } else {//其它非特殊情况全部放行
                view.loadUrl(url);
            }
        }
        return true;
    }
}
创建web.html并放入assets资源文件夹下,同时将WebViewJavascriptBridge.js也拷入

<html>
<head>
    <meta content="text/html; charset=utf-8" http-equiv="content-type">
    <title>
        js调用java
    </title>
</head>
 
<body>
<p>
    <xmp id="show">Native将要回传回来的数据展示</xmp>
</p>
 
<p>
    <input type="text" id="uname" value="用户名"/>
</p>
 
<p>
    <input type="text" id="psw" value="密码"/>
</p>
 
<p>
    <input type="button" id="send" value="发消息给Native" οnclick="sendClick();"
    />
</p>
 
<p>
    <input type="button" id="use" value="调用Native方法" οnclick="useClick();"
    />
</p>
 
<p>
    <input type="file" id="open" value="打开文件" οnclick="onOpen();"/>
</p>
 
<p>
    <a href="tel:110">拨打电话110</a>
</p>
 
<p>
    <a href="http://www.baidu.com">webview浏览器</a>
</p>
 
<p>
    <a href="https://www.csdn.net">调用系统浏览器</a>
</p>
</body>
 
<script>
 
    //Native方法直接调用,示例代码:mBridgeWebview.loadUrl("javascript:nativeFunction('" + data + "')");
    function nativeFunction(data) {
        document.getElementById("show").innerHTML = data;
    }
 
    //h5直接通过send向Native发送消息,在MyHandlerCallBack的Handler里接收,并可通过onCallBack方法回传
    function sendClick() {
        var name = document.getElementById("uname").value;
        var pwd = document.getElementById("psw").value;
        var data = "name = " + name + ", password = " + pwd;
 
        window.WebViewJavascriptBridge.send(
            data,
            function(responseData) {
                document.getElementById("show").innerHTML = responseData
            }
        );
    }
 
    //h5通过和Native统一命名方法名,如submitFromWeb来调取java代码,如mBridgeWebview.registerHandler("submitFromWeb", new BridgeHandler() {...});
    function useClick() {
            var name = document.getElementById("uname").value;
            var pwd = document.getElementById("psw").value;
            var data = "name = " + name + ", password = " + pwd;
 
            window.WebViewJavascriptBridge.callHandler(
                'submitFromWeb', {'info':data},
                function(responseData) {
                    document.getElementById("show").innerHTML = responseData;
                }
            );
     }
 
    function onOpen() {
            var data = "调用文件";
            //call native method
            window.WebViewJavascriptBridge.callHandler(
                'functionOpen'
                , {'param': data }
                , function(responseData) {
                    document.getElementById("open").innerHTML = responseData;
                }
            );
    }
 
/****************************************************************/
    function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }
 
    // 第一连接时初始化bridage
    connectWebViewJavascriptBridge(function(bridge) {
            //也注册默认的Handler,用来接收java调用的send(string,CallBackFunction)方法
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                var data = {
                    'Javascript Responds': '测试中文!'
                };
                console.log('JS responding with', data);
                responseCallback(data);
            });
            //注册handler等待java代码调用
            //初始化时获取数据是调用此处代码
            //参数:标识,要传递到JAVA的数据,回调方法。
            //JAVA代码响应的方法:mBridgeWebview.callHandler("functionInJs", new Gson().toJson(实体类对象), new CallBackFunction(){onCallBack(String data)}
            bridge.registerHandler("functionInJs", function(data, responseCallback) {
                document.getElementById("show").innerHTML = ("data from Java: = " + data);
                var responseData = "I am javascript, Data reception success!";
                responseCallback(responseData);
            });
    })
/****************************************************************/
</script>
</html>

最后不要忘了加网络权限哦
<uses-permission android:name="android.permission.INTERNET"/>
四、总结
1、如果使用registerHandler,那么native和js中定义的标识必须一致

2、大家如果有出现上传文件图片失败,可能是适配原因,安卓系统5.0以上需要在WebChromeClient中实现onShowFileChooser()方法,详情请看代码示例

以上总结不完全,代码中如有错误欢迎指正。

完整代码已上传至GitHub:jsbridge地址

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
是的,为了实现在Web页面中与iOS和Android原生应用程序之间的交互,可以使用JSBridgeJSBridge是一个桥接工具,可以将JavaScript与原生应用程序之间的通信连接起来。 在iOS中,可以使用JavaScriptCore框架和WKWebView来实现JSBridge。在Android中,可以使用WebView和JavaScriptInterface来实现JSBridge。 具体来说,需要在原生应用程序中创建一个JavaScriptInterface类,该类可以实现JavaScript与原生代码之间的通信。然后在Web页面中,可以通过JavaScript调用原生应用程序中的方法。 例如,在iOS中,可以使用以下代码创建一个JavaScriptInterface类: ``` @objc class JSInterface: NSObject { weak var webView: WKWebView? init(webView: WKWebView) { self.webView = webView super.init() } @objc func showToast(_ message: String) { let alertController = UIAlertController(title: "Toast", message: message, preferredStyle: .alert) let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) alertController.addAction(okAction) self.webView?.viewController?.present(alertController, animated: true, completion: nil) } } ``` 然后在Web页面中,可以通过以下代码调用原生应用程序中的showToast方法: ``` window.webkit.messageHandlers.jsInterface.postMessage({action: 'showToast', message: 'Hello world!'}); ``` 在Android中,可以使用以下代码创建一个JavaScriptInterface类: ``` public class JSInterface { private Context context; public JSInterface(Context context) { this.context = context; } @JavascriptInterface public void showToast(String message) { Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } } ``` 然后在Web页面中,可以通过以下代码调用原生应用程序中的showToast方法: ``` window.jsInterface.showToast('Hello world!'); ``` 通过这种方式,可以实现JavaScript与iOS和Android原生应用程序之间的交互

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值