浅谈混合开发与Android,JS数据交互
来源:互联网 发布:pc预测软件 编辑:程序博客网 时间:2024/04/30 15:19
本文是作者原创,如转载请注明出处!
一.概论
现在时代已经走过了移动互联网的超级火爆阶段,市场上移动开发人员已经趋于饱和,显然,只会原生APP的开发已不能满足市场的需求,随着H5的兴起与火爆,H5在原生APP中的使用越来越广泛,也就是我们常说的混合开发(Hybrid APP).最新很火的微信小程序相信大家都是知道的,实际上微信小程序加载的界面就是一个HTML5的界面,HTML5界面在一些电商类的APP中主要承担展示数据的作用,但是他的作用并不仅限于此,最起码js调用原生方法和原生调用js的方法是必须的,我们看到的现在微信小程序中的膜拜单车入口,进入后的扫码功能,就是js调用安卓原生的摄像头进行扫码的,另外分享功能以及点击js中的一个按钮跳转到APP原生界面这些需求都是很常见的,所以js和原生方法的相互调用是必须会的.最近做HTML5相关的地图APP,正好用到了相关的知识,总结下项目中遇到的坑.
二.JS与Android交互
1.Android如何加载一个H5界面到APP?
目前比较成熟的方案是采用Android封装好的中间件WebView.
加载方式
//创建一个WebView,也可以直接在布局中写WebView控件WebView mWebView = new WebView(mContext);//加载网络上的一个urlString url = "https://www.baidu.com";mWebView.loadUrl(url);//加载本地的一个url,asserts目录下的mWebView.loadUrl("file:///android_asset/index.html");
WebView的一些重要设置
//先获取到WebSettings控制类WebSettings settings = mWebView.getSettings();//设置支持javascriptsettings.setJavaScriptEnabled(true);//设置为false表示将图片调整为适合WebView的大小settings.setUseWideViewPort(false);//设置可以访问文件settings.setAllowFileAccess(true);settings.setAllowContentAccess(true);settings.setAllowFileAccessFromFileURLs(true);//设置js支持数据库settings.setDatabaseEnabled(true);//设置js支持window.localStorage,如果不设置,js中获取的window和localStorage都是null,之前我就被坑了,项目中js界面用到了window.localStorage,然后我和js采用alert的方式调试的过程中,发现这个方法一直报错才找到的这个api.settings.setDomStorageEnabled(true);mWebView.loadUrl("file:///android_asset/index.html");//添加了一个java和js交互的接口,android字符串相当于一个Brige桥梁的作用,安卓4.2以后增加了@JavascriptInterface接口,只有代码@JavascriptInterface注解的方法js才能调用,之前是被注入的类和从父类继承的所有的public的方法都能访问,这也是进一步保证APP的安全性.mWebView.addJavascriptInterface(mSnMap, "android");//设置WebView是否加载完成的监听mWebView.setWebViewClient(new WebViewClient() { @Override //WebView加载完成会调用的方法 public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override //WebView开始加载调用的方法 public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); @Override //WebView的界面可见时调用的方法 public void onPageCommitVisible(WebView view, String url) { super.onPageCommitVisible(view, url); } @Override //是否要拦截js和java调用的方法 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return true; } }); //该设置保证加载界面时会自动调用系统的浏览器,而不是提示给用户让用户去选择哪个浏览器mWebView.setWebChromeClient(new WebChromeClient(){ //对应js中的alert()方法,可以重写该方法完成与js的交互 @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } //对应js中promt(),可以重写该方法完成与js的交互 @Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { return super.onJsPrompt(view, url, message, defaultValue, result); } //对应js中的console.log方法,可以重写该方法完成与js的交互 @Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { return super.onConsoleMessage(consoleMessage); } });
java调用js的方法
//比如我要调用addline(jsonline)方法,这里给出我写的一个示例//WebView规定java和js交互的时候前面的字段是javascript:+方法名//注意:传变量的时候注意要给字符串加上两个单引号,传递方式就是我下面写的那种规范public void addLine(Line line) { if (line != null) { jsonLine = mGson.toJson(line); mWebView.loadUrl("javascript:addLine('" + jsonLine + "')"); } }
js调用java的方法
//这里介绍一种最简单的方式,当然也可以自己使用伪协议去封装//1.添加一个交互的接口,mSnMap表示要注入的java类,android是桥接字符串,js调用的使用就使用这个字符串进行交互mWebView.addJavascriptInterface(mSnMap, "android");//2.在js中调用,比如要调用本地读取二进制文件的一个方法@JavascriptInterface public String readshape(String mapshape) { Gson gson = new Gson(); MapShape mapShape = gson.fromJson(mapshape, MapShape.class); String shapeBase64 = SEInterfacePvReader.getMapShape(mapShape); System.out.println(shapeBase64); return shapeBase64; }//3.js调用并获取返回值,另外解释一下,js调用java的方法是在WebView的一个独立的后台线程中,另外这里js调用Android的方法时传递参数只能传一个,而且java与js交互的方法是不支持二进制流交互的,只支持简单的基本数据类型,比如int,boolean,String,数组也是不支持的,数组可以采用json字符串的形式var bufferData = android.readshape(json);
三.数据结构,文件读取
文件读取这块内容,因为矢量数据的存储结构不是我们公司的人设计的,是和我们公司合作的人设计的,他们的服务器代码采用的是C++结合lua脚本语言共同编写的,涉及到数据结构的具体详情不变透漏,主要说下C++和java数据结构的差别以及读取数据时选择的API.
1.C++中的char和java中的char
C++中的char与IOS object-c中的char一样,都是占一个byte
java中的char占2个byte
所以在数据读取过程中c++经常创建一个vector buf就等价于java中读取文件时创建的byte数组.这里用到了java中int转byte数组的工具类.
//具体使用高位到低位还是低位到高位根据具体数据结构而定 public static byte[] intToByteArray(int i) { byte[] result = new byte[4]; //由高位到低位// result[0] = (byte)((i >> 24) & 0xFF);// result[1] = (byte)((i >> 16) & 0xFF);// result[2] = (byte)((i >> 8) & 0xFF);// result[3] = (byte)(i & 0xFF); //低位在前 //由低位到高位 result[0] = (byte) (i & 0xFF); result[1] = (byte) ((i >> 8) & 0xFF); result[2] = (byte) ((i >> 16) & 0xFF); result[3] = (byte) ((i >> 24) & 0xFF); return result; } /** * byte[] 转化为int[] ,低位在前的方式 * @param title * @return */ public static int[] byteArrayToIntArray(byte[] title) { int[] array = new int[title.length / 4]; byte[] temp = new byte[4]; int k = 0; for (int i = 0; i < title.length; i++) { temp[i % 4] = title[i]; if (i > 0 && (i+1) % 4 == 0) { array[k] = byteArrayToInt2(temp); k++; } } return array; } /** * byte数组转化为int值的工具类,低位在前 * * @param b * @return byte[]转化为的int数 */ public static int byteArrayToInt2(byte[] b) { int MASK = 0xFF; int result = 0; result = b[0] & MASK; result = result + ((b[1] & MASK) << 8); result = result + ((b[2] & MASK) << 16); result = result + ((b[3] & MASK) << 24); return result; }
2.文件的读取可以选择RandomAccessFile类和FileInputStream类
两个类都能实现读取二进制文件的效果,同时两个类中都有定位到文件的某个位置的方法,但是他们是有区别的.
FileInputStream的skip()方法是相对于当前位置定位的
RandomAccessFile的seek()方法则可以定位到文件的任意位置
下面用代码举个例子
fis.skip(10);fis.skip(5);//执行完这两行代码后读取的输入流FileInputStream定位到文件的第15个字节处raf.seek(10);raf.seek(5);//这两行代码的最终结果是RandomAccessFile最终定位到文件的第5个字节处.//另外需要注意的是:RandomAccessFile是继承于Object的,只是他实现了DataOutput, DataInput,所以可以读文件也可以写文件.而FileInputStream是继承于InputStream的,只能读文件,而我在项目中读文件采用的是InputStream读,ByteArrayOutputStream作为输出流存储数据.
java和js如何交互文件
java和js是不支持直接的二进制流的交互,所以我们就换了一种方式进行交互,将二进制数据读取后使用Base64算法转化为字符串,将字符串传递给js,js再使用Base64算法反编码为二进制数据流.当然除了这种方式外,还有其他的思路,比如移动端开发一个本地的服务器给js发请求,完成数据的交互.
四.项目总结
目前来说,原生与H5的混合开发相对比较成熟,但是现在没有任何一个工具能够在js与java之前完成debug调试,所以项目上遇到问题只能采用日志和alert弹框的方式一步一步排查代码中的错误,调试起来复杂又繁琐,而且java和js在数据交互上依赖浏览器内核,性能上也存在问题,希望不久的将来,技术上能够突破这些瓶颈.地图的开发还是使用原生调用c++的OpenGL绘制矢量地图比较靠谱,之前研究过1个月的OpenGL开发,因为太难以及项目进度比较赶的原因没有继续下去,接下来会抽出更多的时间去完成OpenGL的底层绘制地图,后续的博客也会分享OpenGL的学习之路.
奉上我很喜欢的一句话,与君共勉:比你聪明的人比你还要努力,你又有什么理由不努力呢?
如有不足之处请指正评论,谢谢!
- 浅谈混合开发与Android,JS数据交互
- Android混合开发之WebView与Js交互
- android web混合开发 混合开发实例——JS与Java的交互
- Android混合开发 java和js交互
- Android与H5交互(混合开发)
- 混合开发 H5 与 ios、android 交互
- android native+h5——混合开发初步,通过js交互数据
- Android和HTML5混合开发中android代码与JS交互
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
- h5混合开发之Js和android简单交互
- Android app混合开发,本地应用与htm5交互
- Android混合开发之WebView与Javascript交互
- Android混合开发之WebView与Javascript交互
- Android混合开发之WebView与Javascript交互
- Android混合开发之WebView与Javascript交互
- Android混合开发之WebView与Javascript交互
- 浅谈android、web混合开发
- 常见浏览器兼容问题整理(ie9及以上)
- JZ2440 中断分析
- Android-获取手机上的图片、视频、音频
- web性能优化与最佳实践
- 解决mongodb E11000,原子性问题
- 浅谈混合开发与Android,JS数据交互
- Python 3基础教程2-打印语句和字符串
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 文章标题
- ${}和#{}的区别
- 笔记8-JAVA的初学浅识(Java 的运算符)
- Red Hat/Centos 性能调优
- Java程序员从笨鸟到菜鸟之(二十一)java过滤器和监听器详解