Android 中Java和JavaScript交互入门

简介: 如何实现JavaScript 和java 交互 实现Java和js交互十分便捷。通常只需要以下几步。 WebView开启JavaScript脚本执行 WebView设置供JavaScript调用的交互接口。

如何实现JavaScript 和java 交互

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

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

#直接看示例代码:

java代码如下:

 

package com.ccb.javascript;

import java.net.URISyntaxException;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

@TargetApi(Build.VERSION_CODES.DONUT)
public class JavaScriptDemo extends Activity {

	private static final String LOGTAG = "MainActivity";

	@SuppressLint("JavascriptInterface")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.javascriptdemo);
		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 Intent toastMessage(String message) {
			Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG)
					.show();
			Intent intent = null;
			// Parse intent URI into Intent Object
			int flags = 0;
			boolean isIntentUri = false;
			if (message.startsWith("intent:")) {
				isIntentUri = true;
				flags = Intent.URI_INTENT_SCHEME;
			} else if (message.startsWith("#Intent;")) {
				isIntentUri = true;
			}
			if (isIntentUri) {
				try {
					intent = Intent.parseUri(message, flags);
				} catch (URISyntaxException e) {
					e.printStackTrace();
				}
			}
			startActivity(intent);
			return intent;
		}

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

}

  

前端网页代码

 

<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
<br />
<a onClick="window.control.toastMessage('#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end')" href="";>调用java中的方法</a>
</html>

  

 

调用示例

js调用Java

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

具体调用:

<a onClick="window.control.toastMessage('#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end')" href="";>调用java中的方法</a>

('#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end')  是传递一个打开Activity的Intent。也可以是字符串或者其他。

  

Java调用JS

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

调用js无参无返回值函数

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

  

调用js有参无返回值函数

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

 

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

  

 

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

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

1.Java调用js代码

 

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

  

 

2.js函数处理,并将结果通过调用java方法返回

 

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
}

  

 

3.Java在回调方法中获取js函数返回值

 

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

  

 

4.4处理

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

 

function getGreetings() {
      return 1;
}


java代码时用evaluateJavascript方法调用


private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}

输出结果:

I/MainActivity( 1432): onReceiveValue value=1

注意

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

  

 

疑问解答

Alert无法弹出

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

 

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

  

Uncaught ReferenceError: functionName is not defined

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

 

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代码

public @interface JavascriptInterface {

}

  

代码混淆问题

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

 

keepattributes *Annotation*
keepattributes JavascriptInterface
-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}

  

All WebView methods must be called on the same thread

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

  

 

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回调线程并不是主线程。如打印日志可验证

 

ThreadInfo=Thread[WebViewCoreThread,5,main]

 

 

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

 

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/

目录
相关文章
|
5天前
|
JSON Android开发 数据格式
android与Web服务器交互时的cookie使用-兼谈大众点评数据获得(原创)
android与Web服务器交互时的cookie使用-兼谈大众点评数据获得(原创)
14 2
|
6天前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
【5月更文挑战第3天】本文介绍了如何在Web自动化测试中使用JavaScript执行器(JavascriptExecutor)来完成Selenium API无法处理的任务。首先,需要将WebDriver转换为JavascriptExecutor对象,然后通过executeScript方法执行JavaScript代码。示例用法包括设置JS代码字符串并调用executeScript。文章提供了两个实战场景:一是当时间插件限制输入时,用JS去除元素的readonly属性;二是处理需滚动才能显示的元素,利用JS滚动页面。还给出了一个滚动到底部的代码示例,并提供了详细步骤和解释。
30 10
|
4天前
|
SQL Java 关系型数据库
零基础轻松入门Java数据库连接(JDBC)
零基础轻松入门Java数据库连接(JDBC)
8 0
|
4天前
|
存储 安全 算法
Java一分钟之-Java集合框架入门:List接口与ArrayList
【5月更文挑战第10天】本文介绍了Java集合框架中的`List`接口和`ArrayList`实现类。`List`是有序集合,支持元素重复并能按索引访问。核心方法包括添加、删除、获取和设置元素。`ArrayList`基于动态数组,提供高效随机访问和自动扩容,但非线程安全。文章讨论了三个常见问题:索引越界、遍历时修改集合和并发修改,并给出避免策略。通过示例代码展示了基本操作和安全遍历删除。理解并正确使用`List`和`ArrayList`能提升程序效率和稳定性。
7 0
|
4天前
|
JavaScript 前端开发 Java
Java和Javascript互调的例子
Java和Javascript互调的例子
11 3
|
5天前
|
XML JSON API
转Android上基于JSON的数据交互应用
转Android上基于JSON的数据交互应用
|
5天前
|
Java Android开发
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
|
5天前
|
JavaScript 前端开发 Java
《手把手教你》系列技巧篇(四十)-java+ selenium自动化测试-JavaScript的调用执行-下篇(详解教程)
【5月更文挑战第4天】本文介绍了如何使用JavaScriptExecutor在自动化测试中实现元素高亮显示。通过创建并执行JS代码,可以改变元素的样式,例如设置背景色和边框,以突出显示被操作的元素。文中提供了一个Java示例,展示了如何在Selenium中使用此方法,并附有代码截图和运行效果展示。该技术有助于跟踪和理解测试过程中的元素交互。
8 0
|
6天前
|
Java API 开发工具
java与Android开发入门指南
java与Android开发入门指南
14 0
|
6天前
|
Java
Java一分钟之-类与对象:面向对象编程入门
【5月更文挑战第8天】本文为Java面向对象编程的入门指南,介绍了类与对象的基础概念、常见问题及规避策略。文章通过代码示例展示了如何定义类,包括访问修饰符的适当使用、构造器的设计以及方法的封装。同时,讨论了对象创建与使用时可能遇到的内存泄漏、空指针异常和数据不一致等问题,并提供了相应的解决建议。学习OOP需注重理论与实践相结合,不断编写和优化代码。
27 1