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

      开发的手机项目也进入了最后的关键功能,在手机上嵌入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 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. */
	@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+“”“”“”“”“”“”“”");
							}
						});



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值