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