WebView上实现Java与JavaScript交互
2016-03-16 15:11
363 查看
在安卓开发上,考虑到开发效率和界面更新,有时使用WebView结合web页面技术,可以快速迭代地开发移动应用。WebView加载资源的速度并不慢,但是如果资源多了,就很慢。图片、css、js、html这些资源每个大概需要10-200ms,一般都是30ms以内就行了。但是,WebView是等全部资源加载完成才开始渲染的,所以最后用原生js来写,别用太多jQuery之类的框架,以改善用户体验。
在混合开发中,有时会用到安卓原生SDK,如调用相机、查看相册、录音等,这就需要web页面中的JavaScript能调用到安卓SDK接口。由于Android的WebView是基于webkit内核的,集成了js与java互调的接口函数,可以方便地进行开发使用。
界面布局xml:
java代码:
其中:有几点必须注意的,网上早期关于WebView的描述中,有几点变化。1)安卓4.2以上的版本中使用WebView实现Java与Js互调,java接口需要声明@JavascriptInterface ; 2)WebView要调用setWebChromeClient(),以适应Js等弹窗等实现;3)addJavascriptInterface中绑定的接口中调用JavaScript接口,需要开启子线程来调用(报错:Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. );
HTML代码:
以上html文件,其中javaInterface就是webView中addJavacriptInterface()方法中注入的接口入口名称,通过该名称就可以直接调用Java中的接口。(该html页面需要保持到项目assets目录中,由webView.loadUrl("file:///android_asset/index.html")来加载);
效果图:
其中,对话框弹出:网址为"file://"的网页显示:,如果是服务器上的web页面就会显示源IP地址等等,显然不是我们想要的。下一篇,我们可以重写WebChromeClient来修改对话框、确认框等webView的优化。
在混合开发中,有时会用到安卓原生SDK,如调用相机、查看相册、录音等,这就需要web页面中的JavaScript能调用到安卓SDK接口。由于Android的WebView是基于webkit内核的,集成了js与java互调的接口函数,可以方便地进行开发使用。
界面布局xml:
<RelativeLayout 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" > <WebView android:id="@+id/webView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@+id/linearLayout" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Java调用JavaScript接口" > </Button> </LinearLayout> </RelativeLayout>
java代码:
private WebView webView; private Handler handler = new Handler(); private Button button; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView) findViewById(R.id.webView); //自定义webView设置 WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webView.addJavascriptInterface(new MyJavaScriptInterface(MainActivity.this), "javaInterface"); //如果注释了,javaScript中的alert弹窗等就会失效,不显示 webView.setWebChromeClient(new WebChromeClient()); //webView.setWebChromeClient(new MyWebChromeClient()); //测试webView加载是否正常 //webView.loadUrl("http://www.baidu.com/"); webView.setWebViewClient(new HelloWebView()); webView.loadUrl("file:///android_asset/index.html"); button = (Button) findViewById(R.id.btn); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String param = "bb"; webView.loadUrl("javascript:showTitle('"+param+"')"); } }); } private class HelloWebView extends WebViewClient{ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // TODO Auto-generated method stub view.loadUrl(url); return true; } } /** * 在主线程中定义JavaScript可以调用的安卓接口 * @author CHQ * API 17以后,每个被调用java函数都要叫声明 @JavascriptInterface */ public class MyJavaScriptInterface{ private Context context; public MyJavaScriptInterface(Context context){ this.context = context; } @JavascriptInterface public String toString() { return "this is interface"; } @JavascriptInterface public void clickOnAndroid() { Toast.makeText(context, "js调用安卓:....", Toast.LENGTH_SHORT).show(); } /** * 安卓调用JS接口,要开启子线程调用 */ @JavascriptInterface public void call() { Toast.makeText(context, "安卓客户端再调用JavaScript接口", Toast.LENGTH_SHORT).show(); handler.post(new Runnable() { @Override public void run() { String param = "bb"; webView.loadUrl("javascript:showTitle('"+param+"')"); } }); } }
其中:有几点必须注意的,网上早期关于WebView的描述中,有几点变化。1)安卓4.2以上的版本中使用WebView实现Java与Js互调,java接口需要声明@JavascriptInterface ; 2)WebView要调用setWebChromeClient(),以适应Js等弹窗等实现;3)addJavascriptInterface中绑定的接口中调用JavaScript接口,需要开启子线程来调用(报错:Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. );
HTML代码:
<html> <script type="text/javascript"> //安卓定义的接口1 function callAndroidInterface() { window.javaInterface.clickOnAndroid(); } // function showTitle(param) { alert("传参:"+param); var x = document.getElementById("title"); alert("标题:"+x.innerHTML); } </script> <body> <h3 id="title">关于安卓与JavaScript的交互</h3> <input type="button" value="调用接口1" onclick="callAndroidInterface()"></input> <input type="button" value="测试接口可用性" onclick="showTitle('aa')"></input> <input type="button" value="调用接口2" onclick="window.javaInterface.call()"></input> </body> </html>
以上html文件,其中javaInterface就是webView中addJavacriptInterface()方法中注入的接口入口名称,通过该名称就可以直接调用Java中的接口。(该html页面需要保持到项目assets目录中,由webView.loadUrl("file:///android_asset/index.html")来加载);
效果图:
其中,对话框弹出:网址为"file://"的网页显示:,如果是服务器上的web页面就会显示源IP地址等等,显然不是我们想要的。下一篇,我们可以重写WebChromeClient来修改对话框、确认框等webView的优化。
相关文章推荐
- ios 开发过程中遇到的一些需要注意的地方
- 类似于微信首页右上角弹出view
- 微信模板消息 群发 突破 4条限制
- IBM Security Appscan漏洞--会话标识未更新
- Android系统之路(初识MTK) ------ OTA打包ROM安装系统img等到ZIP
- 浅析iOS中实例方法和类方法
- Android设计模式-适配器模式
- iOS开发 CocoaPods 的安装流程
- 分析iOS Crash文件:符号化iOS Crash文件的3种方法
- 手机端页面 输入法覆盖输入框问题
- 【DeskClock】开机闹钟横竖屏显示不同
- IBM Security Appscan漏洞--通过框架钓鱼
- Android Studio的目录结构图文介绍
- Android学习系列(39)--Android主题和样式之系统篇(上)
- iOS开发系列—Objective-C之Foundation框架
- IBM Security Appscan漏洞--链接注入(便于跨站请求伪造)
- 解决 Line XXXX:StartTag:invalid element Name
- spark java api通过run as java application运行的方法
- 深入浅出 - Android系统移植与平台开发(九)- JNI介绍
- 容易忽略的ADB命令(持续更新中)