Android webview开发中 js与android相互调用

来源:互联网 发布:如何秒杀淘宝优惠券 编辑:程序博客网 时间:2024/05/16 19:21

      开发的手机项目也进入了最后的关键功能,在手机上嵌入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. */@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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 style="white-space:pre"></span>return name;<span style="white-space:pre"></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. */@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);if (newProgress == 100) {// 滚动条消失}}});chart_webview.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {chart_webview.loadUrl(url);return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);}@Overridepublic 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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}@SuppressLint("SetJavaScriptEnabled")private void init() {context = this;// html urlwebView = (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() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);if (newProgress == 100) {// 滚动条消失}}<span style="color:#ff0000;">@Overridepublic 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() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {webView.loadUrl(url);return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);}@Overridepublic 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() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {return true;}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);// 当首次loadurl加载完,重新加载图形的数据activity.loadNowProsssFourCycle(false);}});

当webview弹出无法再thread加载的错误的时候,需要使用如下代码进行解决,这一点尤其要注意:

webview.post(new Runnable() {@Overridepublic void run() {webview.loadUrl("javascript:restoreAllTiParas('"+ jsondefault + "')");webview.loadUrl("javascript:demodigit('"+ digit + "')");System.out.println("第一个图形是否都为空1+“”“”“”“”“”“”“”");}});



1 0
原创粉丝点击