近期工作项目中遇到Android的WebView与js交互问题,之前也知道有这方面的技术可以实现。但在用的过程中,却发现还是需要用电心思。
现把我所了解的分享给大家,希望可以帮助到做类似项目的童鞋。
为方便演示,就在Android_assets下放置一个html。
html中内容展示如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Untitled Document</title> </head> <div id="div" style="width:100px; height:100px; background-color:#099;" οnclick="window.demo.javaMethod()"> </div> <body> </body> <script type="text/javascript"> function changeColor(){ document.getElementById("div").style.backgroundColor='red'; } </script> </html>
先来测试JavaScript调用java方法
步骤:
1.首先需要对WebView开启对JavaScript支持
2.WebView向JavaScript暴露一个接口提供调用
3.html元素通过onClick等事件调用java方法
代码粘贴如下
package com.example.admin.webview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.webkit.JavascriptInterface; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Toast; import java.io.BufferedReader; import java.io.InputStreamReader; public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView= (WebView) findViewById(R.id.webview); WebSettings settings=webView.getSettings(); //开启对JavaScript的支持 settings.setJavaScriptEnabled(true); //加载本地assets下的html文件 webView.loadDataWithBaseURL(null,getFromAssets("test.html"),"text/html","utf-8",null); //参数1 Object对象 参数2 名称 webView.addJavascriptInterface(MainActivity.this,"demo"); } private String getFromAssets(String fileName){ try { InputStreamReader inputReader = new InputStreamReader( getResources().getAssets().open(fileName) ); BufferedReader bufReader = new BufferedReader(inputReader); String line=""; String Result=""; while((line = bufReader.readLine()) != null) Result += line; return Result; } catch (Exception e) { e.printStackTrace(); return null; } } @JavascriptInterface public void javaMethod(){ Toast.makeText(MainActivity.this, "javascript调用了java方法!", Toast.LENGTH_SHORT).show(); } }
效果图
需要注意的地方就是JavaScript中 window.展露名称.方法名 这里必须对应
步骤:
1.开启JavaScript支持
2.使用WebView的loadURl方法调用JavaScript方法
代码粘贴如下
package com.example.admin.webview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; import java.io.BufferedReader; import java.io.InputStreamReader; public class MainActivity extends AppCompatActivity { private WebView webView; private Button bt_test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView= (WebView) findViewById(R.id.webview); bt_test= (Button) findViewById(R.id.bt_test); WebSettings settings=webView.getSettings(); //开启对JavaScript的支持 settings.setJavaScriptEnabled(true); //加载本地assets下的html文件 webView.loadDataWithBaseURL(null,getFromAssets("test.html"),"text/html","utf-8",null); bt_test.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { webView.loadUrl("javascript:changeColor()"); } }); } private String getFromAssets(String fileName){ try { InputStreamReader inputReader = new InputStreamReader( getResources().getAssets().open(fileName) ); BufferedReader bufReader = new BufferedReader(inputReader); String line=""; String Result=""; while((line = bufReader.readLine()) != null) Result += line; return Result; } catch (Exception e) { e.printStackTrace(); return null; } } }
效果图 点击测试按钮 调用js方法 将div颜色改变为红色
这也就是普遍的WebView与js交互的方式
那么问题来了,如果JavaScript方法有返回值时候,会怎么样?
先来测试一下
修改html中JavaScript代码为
<script type="text/javascript"> function changeColor(){ document.getElementById("div").style.backgroundColor='red'; return "qwertyuiop"; } </script>再点击按钮
这个时候WebView出现了重定向
解决方案如下
在Android4.4以后,WebView新增了一个API--evaluateJavascript(String script,ValueCallback<ResultType>)
用法如下
bt_test.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { webView.evaluateJavascript("changeColor()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Toast.makeText(MainActivity.this, "返回值"+value, Toast.LENGTH_SHORT).show(); } }); } });效果如下
至于4.4之前的该怎么办?
目前的解决方案是通过java反射机制
在android.webkit包中有个BrowserFrame私有类,该类中有个Native方法:
public native String stringByEvaluatingJavaScriptFromString(String script)
使用步骤
1.扩展WebView添加方法,并使用反射实现。
2.将布局文件中的WebView修改为自定义的WebView
3.使用新的WebView调用方法,执行js方法获取返回值
自定义WebView如下
public String stringByEvaluatingJavaScriptFromString(String script) {
try {
//由webview取到webviewcore
Field field_webviewcore = WebView.class.getDeclaredField("mWebViewCore");
field_webviewcore.setAccessible(true);
Object obj_webviewcore = field_webviewcore.get(this);
//由webviewcore取到BrowserFrame
Field field_BrowserFrame = obj_webviewcore.getClass().getDeclaredField("mBrowserFrame");
field_BrowserFrame.setAccessible(true);
Object obj_frame = field_BrowserFrame.get(obj_webviewcore);
//获取BrowserFrame对象的stringByEvaluatingJavaScriptFromString方法
Method method_stringByEvaluatingJavaScriptFromString = obj_frame.getClass().getMethod("stringByEvaluatingJavaScriptFromString", String.class);
//执行stringByEvaluatingJavaScriptFromString方法
Object obj_value = method_stringByEvaluatingJavaScriptFromString.invoke(obj_frame, script);
//返回执行结果
return String.valueOf(obj_value);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
转自:https://blog.csdn.net/sy18298711239/article/details/51945478