android native+h5——混合开发初步,通过js交互数据
先来说说大概:
native app中布局很简单,就一个webview,这里就不贴出来了。
前端包含一个index.html 和一个index.js;里面是测试数据
先来说说实现哪些功能:
1,native app显示html
2,模拟服务器端的html和js
3,通过协商的方法完成 native app调用前段js中的数据
4,通过协商的方法完成native app 回馈给js信息(也就是app和前端 js的双向调用)
先看看成功调用js后的效果图:

1,index.html代码
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Hello Native+H5!</title>
<script type="text/javascript" charset="UTF-8" src="../js/index.js"></script>
<script type="text/javascript" charset="UTF-8">
function showMessage() {
control.showToast("欢迎使用native+h5");
} </script></head><body>
<input type="button" value="欢迎1" onclick="showToast('Hell_Native+H5')" />
<input type="button" value="欢迎2" onclick="showMessage()" />
<input type="button" value="警告" onclick="onAlert()" />
<input type="button" value="确定" onclick="onConfirm()" />
<input type="button" value="提示" onclick="onPrompt()" /></body></html>2,index.js代码
function loadingImg() {
alert("欢迎使用native+h5");
}//android中的toast显示信息框function showToast(toast) {
android.showToast(toast);
}//警告 function onAlert() {
alert("This is a alert sample from html");
}//确定 function onConfirm() {
//得到true/false
var b = confirm("are you sure to login?");
control.showToast("your choice is " + b);
}//提示 function onPrompt() {
//得到输入内容
var b = prompt("please input your password", "aaa");
control.showToast("your input is " + b);
}//用于app向js反向输出日志function info(msg) {
console.info(msg);
}3,MainActivity.javaM代码
package com.example.hellonativeh5;public class MainActivity extends Activity {
private WebView native_web; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
native_web = (WebView) findViewById(R.id.native_web);
initWeb();
} /**
* 初始化webview 允许js后要小心XSS攻击了
*
* @JavascriptInterface这个注解 在4.2以上修复了,但是需要注意兼容性
*/
@SuppressLint("SetJavaScriptEnabled") private void initWeb()
{
WebSettings webSettings = native_web.getSettings();
//
webSettings.setJavaScriptEnabled(true);
// 第一个参数里面包含了需要从js调用的方法或者反向回馈给js的方法
// 第二个参数调用的是和js里规定的方法一样,调用function:android中的方法showToast,前缀javascript可有可无
// js代码:
// function showToast(toast) {
// android.showToast(toast);
// }
// 在js中,android.showToast(toast);是不能被执行的,
可能在html中执行会报错。因为它是js和原生app协商后定义的方法,不是js原有方法
native_web.addJavascriptInterface(new JsInterface(), "android");
// 设置拦截js中的三种弹框
native_web.setWebChromeClient(new MyWebChromeClien());
// 监听点击的每一个url,做自己的特殊处理用
native_web.setWebViewClient(new MyWebViewClient());
// 加载项目asset文件夹下的本地html
native_web.loadUrl("file:///android_asset/h5/html/index.html");
// 加载本地的html布局文件
// 加载 asset 文件的内容,第二种加载本地html的方法
String tpl = getFromAssets("h5/html/index.html");
// native_web.loadDataWithBaseURL(null, tpl, "text/html", "utf-8",null);
}
/*
* 获取html文件的内容
*/
public 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 "";
} /**
* 监听 所有点击的链接,如果拦截到我们需要的,就跳转到相对应的页面。
*/
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("webview", "url===>" + url);
try
{
// 如果url满足某种特定的格式,则进行特殊处理
if (url.contains("http://")) {
view.loadUrl(url);
} else {
view.loadUrl(url);
} return true;
} catch (Exception e) { return true;
}
}
} /**
* 拦截js的提示框
*/
private class MyWebChromeClien extends WebChromeClient {
// 提示框
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
final JsPromptResult result) {
new AlertDialog.Builder(MainActivity.this).setMessage(message)
.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// 当弹出框点击的时候,手动用代码给js返回确认的信息
result.confirm("true");
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
result.cancel();
}
}).show();
// 返回false会弹出原声dialog,这里不让原声的弹出
return true;
} // 警告框
@SuppressLint("NewApi") @Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
// api 17以后才有onDismiss 接口,这里稍作处理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
new AlertDialog.Builder(MainActivity.this).setMessage(message)
.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
// TODO Auto-generated method stub
result.cancel();
}
}).show();
} else {
AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).setMessage(message)
.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) { // 当弹出框点击的时候,手动用代码给js返回确认的信息
result.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.setCancelable(false);
} return true;
} // 确认框
@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result)
{
new AlertDialog.Builder(MainActivity.this).setMessage(message)
.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// 当弹出框点击的时候,手动用代码给js返回确认的信息
result.confirm();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
result.cancel();
}
}).show(); return true;
}
} /**
* 对应js中的调用方法
*/
public class JsInterface {
//这个方法就是js中带有android.前缀的方法名
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
// 当显示出toast的时候,就向js反向输出一条log
log("show toast success");
} //这里是将app产生的信息回馈给js
public void log(final String msg) {
native_web.post(new Runnable() { @Override
public void run() { // 调用js中指向info的方法
// 这个方法会将信息在浏览器的控制台的info中显示出来
native_web.loadUrl("info(" + "'" + msg + "'" + ")");
}
});
}
}
}这里需要注意的是:js中的特定方法是前段和app端协商定义下的方法名和参数名,是不受js控制的
也就是说,如果在前端调用了这些“特殊”的方法,前端会报错。
如果你向深入的了解native+h5 那么一定要熟悉js/html和css;
因为如果没有其他人给你做前端页面的话,你自己可能就要亲自去写这些了。
就算有人给你完好的html和js,你也得会看,会调用。
实战中的js和html可没有这么简单。
上述功能是点击html页面中的js代码,实现js对android的回调。还有一种,直接使用android代码调用js,与之前的相反,实现android调用js代码。
这个就很简单了:
web_view.loadUrl("hideDown()");//直接loadUrl。hideDown()是html中的js代码方法名转载自:http://blog.csdn.net/yehui928186846/article/details/53381366