开发的手机项目也进入了最后的关键功能,在手机上嵌入html5图形,需要与android和js进行相互交互,百度了一下android的webview提供了强大的调用js的功能,也可以将android的对象传入到html界面进行使用,不多说上代码(关键在android调用js的函数,传递多个函数的写法,网上没有多少例子):
1.html文件,demo.html
<html>
<head>
<script type="text/javascript" >
function updateHtml(type,type2){
document.getElementById("content").innerHTML =
"弹出对话框,测试"+type+type2;
alert("dialog");
}
</script>
</head>
<body>
这是一个js与android的例子 <a onClick="window.ceshi.startFunction()" href="">弹出对话框</a>
调用对象方法 <a onClick="per.print()" href="">调用对象方法</a>
<span id="content"></span>
</body>
</html>
2.android端控制代码:
package com.ccb.javascript;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
int priceMenu1 = 1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取webView 控件
final WebView webview = (WebView) findViewById(R.id.webview);
// 加上这句话才能使用javascript方法
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("file:///android_asset/demo.html");
webview.addJavascriptInterface(new Person(this), "per");
Button button = (Button) findViewById(R.id.button); // 获取button控件
// 即"调用html中的js方法"
// 按钮
// 给button添加事件响应,执行JavaScript的fillContent()方法
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
webview.loadUrl("javascript:updateHtml('str11','bar22')");//多个参数拼接
}
});
Button button1 = (Button) findViewById(R.id.button1);// 获取button1控件
// 即"重新加载html "按钮
// 给button添加事件响应,执行JavaScript的fillContent()方法
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("MainActivity", "button1 OnClick");
webview.loadUrl("file:///android_asset/demo.html");
// return
}
});
// 增加接口方法,让html页面调用
webview.addJavascriptInterface(this, "ceshi");
Button buttonceshi = (Button) findViewById(R.id.buttonceshi);
buttonceshi.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
public void startFunction() {
AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this);
ab.setTitle("提示");
ab.setMessage("通过js 调用了 java 中的方法");
ab.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
ab.create().show();
}
class Person {
Context mContext;
Person(Context c) {
mContext = c;
}
String name = "我的名字是对象";
int age;
public String getName() {//js里面无法直接使用对象加属性的方式访问,暂时没找到方法,只能用对象加getName
<span > </span>return name;
<span > </span>}
public void print() {
Toast.makeText(mContext, "你好", Toast.LENGTH_LONG).show();
System.out.println("我成功的调用了对象");
}
}
}
运行结果如下:
有问题可以探讨,关于html5的部分我也不太懂,以后会好好研究一下
========================分割线,2015年11月13日11:06:24=============================
增加传递list对象数组到js里面:
1.java代码如下:
package com.ccb.javascript;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
int priceMenu1 = 1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取webView 控件
final WebView webview = (WebView) findViewById(R.id.webview);
// 加上这句话才能使用javascript方法
webview.getSettings().setJavaScriptEnabled(true);
// webview.loadUrl("http://128.128.191.62/cn/mobile/geturl.html");
// 加载assets目录下面的demo.html 界面
webview.loadUrl("file:///android_asset/demo.html");
webview.addJavascriptInterface(new Person(this), "per");
List<Person> programList = initProgramList();
webview.addJavascriptInterface(programList, "programList");
Button button = (Button) findViewById(R.id.button); // 获取button控件
// 即"调用html中的js方法"
// 按钮
// 给button添加事件响应,执行JavaScript的fillContent()方法
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
webview.loadUrl("javascript:updateHtml('str11','bar22')");
}
});
Button button1 = (Button) findViewById(R.id.button1);// 获取button1控件
// 即"重新加载html "按钮
// 给button添加事件响应,执行JavaScript的fillContent()方法
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("MainActivity", "button1 OnClick");
webview.loadUrl("file:///android_asset/demo.html");
// return
}
});
// 增加接口方法,让html页面调用
webview.addJavascriptInterface(this, "ceshi");
Button buttonceshi = (Button) findViewById(R.id.buttonceshi);
buttonceshi.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
public void startFunction() {
AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this);
ab.setTitle("提示");
ab.setMessage("通过js 调用了 java 中的方法");
ab.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
ab.create().show();
}
// 初始化数据
private List<Person> initProgramList() {
List<Person> list = new ArrayList<Person>();
for (int i = 1; i <= 10; i++) {
Person p = new Person("测试", i);
list.add(p);
}
return list;
}
class Person {
Context mContext;
Person(Context c) {
mContext = c;
}
Person(String name, int age) {
this.name = name;
this.id = age;
}
String name;
public void setName(String name) {
this.name = name;
}
int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void print() {
Toast.makeText(mContext, "你好" + name, Toast.LENGTH_LONG).show();
System.out.println("我成功的调用了对象");
}
}
}
2.html里的js代码如下:
<html>
<head>
<script type="text/javascript">
var startTop = 120;
var startPos = 1;
var totalNum = 0;
var itemHeight = 40;
var con1 = '';
function updateHtml(type, type2) {
totalNum = window.programList.size();
if (window.programList) {
//初始化页面
totalNum = window.programList.size();
for (i = 0; i < totalNum; i++) {
con1 += programList.get(i).getId()
+ programList.get(i).getName();
}
}
document.getElementById("content").innerHTML = "弹出对话框,测试" + type
+ type2 + "测试" + totalNum + con1;
alert("dialog");
}
</script>
</head>
<body>
这是一个js与android的例子
<a onClick="window.ceshi.startFunction()" href="">弹出对话框</a> 调用对象方法
<a onClick="ceshi()">调用对象方法</a>
<span id="content"></span>
</body>
</html>
注意点:如果使用webview.loadURL方法传参数,参数的书写形式应该按照如下形式:
webview.loadURL( "javascript:chooseManyLines('" + type + "')");也就是参数需要使用' ',进行包含,否则无法识别该参数。就不能调用js的函数。
============================分割线,2015年11月17日09:47:39================================
上述android与js的交互,传递List对象,的确可以在js中遍历该list对象,但在测试的时候发现这样的问题,list中存有超过300条数据的时候,android程序就会意外终止退出,看后台打印的消息:应该是内存泄露,找过各种资料,还是未解决,期待大神解答!!!!
后来同事的解决方式是:不使用
webview.addJavascriptInterface(programList, "programList");传递List对象
1. 改用JSON,传递JSON数据到js里面,这样就避免了不断地创建对象导致的内存泄露问题,JSON将LIST数据转换为String类型的操作类如下:
package client.verbank.mtp.allone.util;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import jedi.verbank.CSTS3.comm.struct.HistoricData;
public class JSONUtil {
public static String getJSON4HistoryData(List<HistoricData> historicDataList) {
JSONArray array = new JSONArray();
if (historicDataList == null) {
return "";
}
for (HistoricData data : historicDataList) {
JSONObject object = new JSONObject();
try {
object.put("3", data.getOpenPrice());
object.put("7", data.getVolume());
object.put("4", data.getHighPrice());
object.put("5", data.getLowPrice());
object.put("1", data.getDataTime());
object.put("6", data.getClosePrice());
} catch (JSONException e) {
e.printStackTrace();
}
array.put(object);
}
return array.toString();
}
}
2. 用webview将该JSON的String传递到js里面,代码如下:
chart_webview.loadUrl("javascript:ceshi("
+ queryHisData() + ",800,1,1)");
3. js里的代码如下,将json数据拆分:
function ceshi(historicDatas, numberOfTicks, timeSpanInMinutes,
optMergeSpanTimeInMinutes) {
// 讓時間對齊跨度。
var timeSpanInMsec = timeSpanInMinutes * 60 * 1000;
// 開始產生tick。
var tempTickList = [];
for (var i = 0; i < numberOfTicks; ++i) {
var tick = {
high : historicDatas[i]["4"],
low : historicDatas[i]["5"],
open : historicDatas[i]["3"],
close : historicDatas[i]["6"],
volume : historicDatas[i]["7"],
timestamp : historicDatas[i]["1"],
}
tempTickList.push(tick);
}}
这样就大功告成了!!!!关键是使用JSON格式保存List对象数据
====================================分割线,2015年12月1日09:27:20,增加疑问===========================================================
后面开发遇到这样的问题,使用
webview.addJavascriptInterface(programList, "programList") 有一个限定条件,需要接着webview.getSettings().setJavaScriptEnabled(true);
// webview.loadUrl("http://128.128.191.62/cn/mobile/geturl.html");
// 加载assets目录下面的demo.html 界面
webview.loadUrl("file:///android_asset/demo.html");之后才会生效,在另一个activity里面,无法传递对象到js里面,后面也只能使用json的方式传递到js里面。
=============================分割线,2015年12月4日09:47:15======================================
android与js相互调用,js页面总会存在错误,但写了alert,却没有弹出错误窗口,后来查资料发现如要设置如下属性才能弹出错误窗口,如下:
chart_webview = (WebView) activityView.findViewById(R.id.chart_webview);
chart_webview.getSettings().setBuiltInZoomControls(true);
chart_webview.getSettings().setJavaScriptEnabled(true);
chart_webview.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
// 滚动条消失
}
}
});
chart_webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
chart_webview.loadUrl(url);
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
chart_webview.loadUrl(CandlestickChart.url);
2.如果要想将js里面的函数返回值传递给android代码中使用,可以使用如下方式:
package com.example.androidinvokejs;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.webkit.JsResult;
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 WebView webView;
private Context context;
String jsonStr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
@SuppressLint("SetJavaScriptEnabled")
private void init() {
context = this;
// html url
webView = (WebView) findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setSupportZoom(true);
settings.setBuiltInZoomControls(true);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
// 滚动条消失
}
}
<span style="color:#ff0000;">@Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
System.out.println("从js文件拿到的数据为" + message + "=============");
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
result.confirm();
return true;
}</span>
});
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webView.loadUrl(url);
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
webView.loadUrl("file:///android_asset/index.html");
<span style="color:#ff0000;">webView.loadUrl("javascript:alert(1)");</span>
webView.addJavascriptInterface(new JavascriptInterface(), "jsInterface");
// webView.loadUrl("javascript:ceshi()");
}
class JavascriptInterface {
@SuppressWarnings("unused")
@android.webkit.JavascriptInterface
/** 解决Android 17(包括17)之后js无法调用Android方法*/
public void ceshi(String json) {
jsonStr = json;
System.out.println("从js传递过来的js字符串为:" + jsonStr);
Toast.makeText(context, jsonStr, Toast.LENGTH_LONG).show();
try {
// 解析js传递过来的json串
JSONObject mJson = new JSONObject(json);
String name = mJson.optString("name");
Toast.makeText(context, name, Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
//=================================分割线,2016年5月6日10:18:10===================================
使用webview的loadurl需要知道页面什么时候能加载完,所以需要使用webview的pagefinish加载完的回调函数,如下代码:
four_chart_webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 当首次loadurl加载完,重新加载图形的数据
activity.loadNowProsssFourCycle(false);
}
});
当webview弹出无法再thread加载的错误的时候,需要使用如下代码进行解决,这一点尤其要注意:
webview.post(new Runnable() {
@Override
public void run() {
webview.loadUrl("javascript:restoreAllTiParas('"
+ jsondefault + "')");
webview.loadUrl("javascript:demodigit('"
+ digit + "')");
System.out
.println("第一个图形是否都为空1+“”“”“”“”“”“”“”");
}
});