Android WebView與JavaScript交互詳解


近期工作項目中遇到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;" onclick="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.展露名稱.方法名    這里必須對應


下面是java調用js方法

步驟:

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;

    }

}





注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com