混合开发因为其高度的可扩展性和维护性,很多公司都采用了这种开发方式,对于安卓客户端来说,除了核心的WebView,涉及到最多的就是JAVA与JS的交互。本文旨在简单的介绍一下JS与JAVA的交互。
JS与JAVA的交互式通过java bridge来实现的,官方是这么介绍他的:
The PHP/Java Bridge is an implementation of a streaming, XML-based network protocol, which can be used to connect a native script engine, for example PHP, Scheme or Python, with a Java virtual machine. It is up to 50 times faster than local RPC via SOAP, requires less resources on the web-server side. It is faster and more reliable than direct communication via the Java Native Interface, and it requires no additional components to invoke Java procedures from PHP or PHP procedures from Java.
对于客户端来说,既需要能够调用到JS的方法,也需要JS能够调用到java的本地方法。
他们之间的沟通是建立在WebView之上的。
话不多说,先上个Demo
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.webView);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
webView.setWebViewClient(new WebViewClient());
webView.addJavascriptInterface(new JavaScriptinterface(this,webView),"wh");
webView.loadUrl("file:///android_asset/index.html");
}
}
该Activity只有一个简单的WebView布局,首先需要WebView支持JavaScript,设置
settings.setJavaScriptEnabled(true);
注意:此处容易产生内存泄漏,所以在Activity进入后台的时候,最好停止JS的加载。
核心语句是:
webView.addJavascriptInterface(new JavaScriptinterface(this,webView),"wh");
该方法给WebView添加了一个JS的接口,第一个参数是一个Object类型,所以可以自己定义一个类即可。第二个参数是一个字符串类型的name,这个参数是和前端约定好的方法调用者的名字。(稍后会看到)
设置完后,可以加载网页了,这个网页是一个本地的html文件。
接下来,我们看看这个借口的具体代码:
public class JavaScriptinterface {
private Context context;
private WebView mWebView;
public JavaScriptinterface(Context c, WebView webView) {
context = c;
mWebView = webView;
}
/**
* 与js交互时用到的方法,在js里直接调用的
*/
@JavascriptInterface
public void showToast(String str) {
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//直接通过webView调用js方法
mWebView.loadUrl("javascript:onSucess(\"回调成功\")");
}
}, 2000);
}
/**
* 与js交互时用到的方法,在js里直接调用的
*/
@JavascriptInterface
public void confirm(String str) {
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
在这个类里面可以看到重要的两个方法添加了
@JavascriptInterface
的注释,这是必不可少的,标识者这个方法是要被JS调用的。
在showToast()方法中简单的弹了一个Toast,并且延迟2秒通过
mWebView.loadUrl("javascript:onSucess(\"回调成功\")");
调用了JS的onSucess(args)方法,这个稍后在html文件中可以看到具体的调用。
我们可以看到showToast方法就是一个普通的java方法。
接下来看看我们的html文件是如何调用该方法的。
分析数据
点击调用安卓相关方法
重点观察两个方法:
在这个方法中,我我们观察到直接调用了:
wh.showToast("js调用安卓");
可以看到方法的调用者wh就是在给WebView添加借口时传递的第二个参数,也就是调用者的name。后面的showToast方法就是java的本地方法。
加载这个网页文件后:点击标签会调用JS的showToast方法。
点击调用安卓相关方法
在Java的showToast方法中,我们又延迟调用了:
mWebView.loadUrl("javascript:onSucess(\"回调成功\")");
该语句就是主动调用JS的onSucess方法,在JS的代码中,为了方便测试,我们有主动调用了java的confirm方法,弹出一个对话框。表示一次交互的完成。
总的来说,JS与JAVA的交互核心就是通过javaBridge,在WebView的基础上来完成的。被JS调用的JAVA方法必须添加@JavaScriptInterface注释,表示该方法是要被JS调用,同时在给WebView添加JS接口的时候,必须保证方法调用者标志和JS的一致。才能完成一次沟通。
JS的支持带参数的方法,因此可以实现JAVA与JS的数据互通。