文档章节

Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScrip

SuShine
 SuShine
发布于 2015/07/06 15:45
字数 1609
阅读 223
收藏 0

Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScript又是一个很举足轻重的脚本。本文将介绍如何实现Java代码和Javascript代码的相互调用。

如何实现

实现Java和js交互十分便捷。通常只需要以下几步。

  • WebView开启JavaScript脚本执行
  • WebView设置供JavaScript调用的交互接口。
  • 客户端和网页端编写调用对方的代码。

本例代码

为了便于讲解,先贴出全部代码

Java代码

lineos:false

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
package com.example.javajsinteractiondemo;  import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast;  public class MainActivity extends Activity {  private static final String LOGTAG = "MainActivity";  @SuppressLint("JavascriptInterface")  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  final WebView myWebView = (WebView) findViewById(R.id.myWebView);  WebSettings settings = myWebView.getSettings();  settings.setJavaScriptEnabled(true);  myWebView.addJavascriptInterface(new JsInteration(), "control");  myWebView.setWebChromeClient(new WebChromeClient() {});  myWebView.setWebViewClient(new WebViewClient() {   @Override  public void onPageFinished(WebView view, String url) {  super.onPageFinished(view, url);  testMethod(myWebView);  }   });  myWebView.loadUrl("file:///android_asset/js_java_interaction.html");  }   private void testMethod(WebView webView) {  String call = "javascript:sayHello()";   call = "javascript:alertMessage(\"" + "content" + "\")";   call = "javascript:toastMessage(\"" + "content" + "\")";   call = "javascript:sumToJava(1,2)";  webView.loadUrl(call);   }   public class JsInteration {   @JavascriptInterface  public void toastMessage(String message) {  Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();  }   @JavascriptInterface  public void onSumResult(int result) {  Log.i(LOGTAG, "onSumResult result=" + result);  }  }  } 

前端网页代码

lineos:false js_java_interaction.html

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<html> <script type="text/javascript">  function sayHello() {  alert("Hello")  }   function alertMessage(message) {  alert(message)  }   function toastMessage(message) {  window.control.toastMessage(message)  }   function sumToJava(number1, number2){  window.control.onSumResult(number1 + number2)  } </script> Java-Javascript Interaction In Android </html> 

调用示例

js调用Java

调用格式为window.jsInterfaceName.methodName(parameterValues) 此例中我们使用的是control作为注入接口名称。

lineos:false

1 2 3 4 5 6 7
function toastMessage(message) {  window.control.toastMessage(message) }  function sumToJava(number1, number2){  window.control.onSumResult(number1 + number2) } 

Java调用JS

webView调用js的基本格式为webView.loadUrl(“javascript:methodName(parameterValues)”)

调用js无参无返回值函数

lineos:false

1 2
String call = "javascript:sayHello()"; webView.loadUrl(call); 

调用js有参无返回值函数

注意对于字符串作为参数值需要进行转义双引号。

lineos:false

1 2
String call = "javascript:alertMessage(\"" + "content" + "\")"; webView.loadUrl(call); 

调用js有参数有返回值的函数

Android在4.4之前并没有提供直接调用js函数并获取值的方法,所以在此之前,常用的思路是 java调用js方法,js方法执行完毕,再次调用java代码将值返回。

1.Java调用js代码

lineos:false

1 2
String call = "javascript:sumToJava(1,2)"; webView.loadUrl(call); 
2.js函数处理,并将结果通过调用java方法返回

lineos:false

1 2 3
function sumToJava(number1, number2){  window.control.onSumResult(number1 + number2) } 
3.Java在回调方法中获取js函数返回值

lineos:false

1 2 3 4
@JavascriptInterface public void onSumResult(int result) {  Log.i(LOGTAG, "onSumResult result=" + result); } 

4.4处理

Android 4.4之后使用evaluateJavascript即可。这里展示一个简单的交互示例 具有返回值的js方法

lineos:false

1 2 3
function getGreetings() {  return 1; } 

java代码时用evaluateJavascript方法调用

lineos:false

1 2 3 4 5 6 7 8
private void testEvaluateJavascript(WebView webView) {  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {   @Override  public void onReceiveValue(String value) {  Log.i(LOGTAG, "onReceiveValue value=" + value);  }}); } 

输出结果

lineos:false

1
I/MainActivity( 1432): onReceiveValue value=1 

注意

  • 上面限定了结果返回结果为String,对于简单的类型会尝试转换成字符串返回,对于复杂的数据类型,建议以字符串形式的json返回。
  • evaluateJavascript方法必须在UI线程(主线程)调用,因此onReceiveValue也执行在主线程。

疑问解答

Alert无法弹出

你应该是没有设置WebChromeClient,按照以下代码设置

1
myWebView.setWebChromeClient(new WebChromeClient() {}); 

Uncaught ReferenceError: functionName is not defined

问题出现原因,网页的js代码没有加载完成,就调用了js方法。解决方法是在网页加载完成之后调用js方法

fileos:false

1 2 3 4 5 6 7 8 9
myWebView.setWebViewClient(new WebViewClient() {   @Override  public void onPageFinished(WebView view, String url) {  super.onPageFinished(view, url);  //在这里执行你想调用的js函数  }  }); 

Uncaught TypeError: Object [object Object] has no method

安全限制问题

如果只在4.2版本以上的机器出问题,那么就是系统处于安全限制的问题了。Android文档这样说的

Caution: If you’ve set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

中文大意为

警告:如果你的程序目标平台是17或者是更高,你必须要在暴露给网页可调用的方法(这个方法必须是公开的)加上@JavascriptInterface注释。如果你不这样做的话,在4.2以以后的平台上,网页无法访问到你的方法。

解决方法
  • 将targetSdkVersion设置成17或更高,引入@JavascriptInterface注释
  • 自己创建一个注释接口名字为@JavascriptInterface,然后将其引入。注意这个接口不能混淆。这种方式不推荐,大概在4.4之后有问题。

注,创建@JavascriptInterface代码

lineos:false

1 2 3
public @interface JavascriptInterface {  } 

代码混淆问题

如果在没有混淆的版本运行正常,在混淆后的版本的代码运行错误,并提示Uncaught TypeError: Object [object Object] has no method,那就是你没有做混淆例外处理。 在混淆文件加入类似这样的代码

lineos:false

1 2 3 4 5
keepattributes *Annotation* keepattributes JavascriptInterface -keep class com.example.javajsinteractiondemo$JsInteration {  *; } 

All WebView methods must be called on the same thread

过滤日志曾发现过这个问题。

lineos:false

1 2 3 4 5 6 7 8 9
E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4}) E/StrictMode( 1546): at android.webkit.WebView.checkThread(WebView.java:2063) E/StrictMode( 1546): at android.webkit.WebView.loadUrl(WebView.java:794) E/StrictMode( 1546): at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96) E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27) E/StrictMode( 1546): at android.os.Handler.dispatchMessage(Handler.java:102) E/StrictMode( 1546): at android.os.Looper.loop(Looper.java:136) E/StrictMode( 1546): at android.os.HandlerThread.run(HandlerThread.java:61) 

在js调用后的Java回调线程并不是主线程。如打印日志可验证

lineos:false

1
ThreadInfo=Thread[WebViewCoreThread,5,main] 

解决上述的异常,将webview操作放在主线程中即可。

1 2 3 4 5 6
webView.post(new Runnable() {  @Override  public void run() {  webView.loadUrl(YOUR_URL).  } }); 

其他

本文转载自:http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/

SuShine
粉丝 128
博文 578
码字总数 158087
作品 0
朝阳
后端工程师
私信 提问
android之在view中内嵌浏览器的方法

我要做的一个东西是在一个页面的中间嵌入浏览器,一开始不知道从哪里开始,因为以前用的都是Textveiw或者editVeiw之类的控件,而它们并不能用来显示网页的内容,怎么办呢? 首先想到的是:是...

迷途d书童
2012/03/24
2.2K
0
WebBrowser(WebView) API (浏览器控件WebView)

一、WP8中的WebBrowser Windows Phone 提供基于桌面浏览器的 WebBrowser 控件。Windows Phone OS 7.1 的 WebBrowser 控件基于 Internet Explorer 9,且 Windows Phone 8 的 WebBrowser 控件基......

失足处男的倒霉孩子
2013/12/27
6.8K
0
Android WebView基本使用

WebView介绍 Android WebView在Android平台上是一个特殊的View, 基于webkit引擎、展现web页面的控件,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。WebView...

临江仙卜算子
2018/07/06
0
0
有关WebView开发问题

如何创建WebView: 1、添加权限:AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。 2、在要Activity中生成一个WebView组件:WebView w......

无鸯
2011/11/09
733
0
android WebView详解

浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview。只是其引擎不同,相对于微软的webbrowser,android及ios的webview的引擎...

amigos_wu
2012/06/25
0
1

没有更多内容

加载失败,请刷新页面

加载更多

在优麒麟中运行英雄联盟LOL

sudo apt install wine-stable sudo add-apt-repository ppa:lutris-team/lutris sudo apt install lutris 在lutris官网的game分类里找到英雄联盟这个游戏,然后进去那个页面, https://lutr......

gugudu
19分钟前
3
0
Mysql主从

一、mysql主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的,MySQL主从基于binlog,主上须开启b...

wxy丶
23分钟前
2
0
商品SKU规格算法

思想 定义规格属性数据格式 定义生成SKU数据格式 完成点击多选框后生成的数据源 根据数据源生成SKU数据 根据生成的SKU数据做展示 代码示例 <!DOCTYPE html><html><head> <!-- 页面met...

chinahufei
31分钟前
0
0
面试点:Java 中 hashCode() 和 equals() 的关系

Java 中 hashCode() 和 equals() 的关系是面试中的常考点,如果没有深入思考过两者设计的初衷,这个问题将很难回答。除了应付面试,理解二者的关系更有助于我们写出高质量且准确的代码。 一....

爱码仕i
33分钟前
3
0
传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式

讲解JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式,并编写两种缓存方式的示例代码。 1.从Java虚拟机创建的对象传到本地C/C++代码时会产生引用,根据Java的垃圾回...

shzwork
44分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部