1、背景
基于业务需要,在移动端需要在无网络环境下完成某些业务操作,然后回到有网络的区域将数据传送到后台,开发模式还是基于webview的混合开发,即界面操作都是由前端代码实现,共用一套后台接口。
所以需要在安卓端区分处理在线模式 和 离线模式。
2、解决方案:
首先想到的第一种方案为: 通过webview里面的url拦截,根据前端请求访问进行拦截处理,然后在离线模式下,访问本地数据库,组装数据
WebResourceResponse
返回给前端。
在方法 shouldInterceptRequest 中处理:
ByteArrayInputStream is = new ByteArrayInputStream(localTargetRes.getBytes());
Map
map.put("Access-Control-Allow-Origin","*");
map.put("Access-Control-Allow-Headers","Content-Type");
WebResourceResponse resourceResponse = new WebResourceResponse("application/json",
"UTF-8",
200,
"OK",
map,
is);
return resourceResponse;
但是调试结果是,无法获取post传递的参数,因为webview的回调中只能够获取url, 已经请求头Header信息,所以此方案并不能达到效果。
方案二: 前端发出的后台数据请求,直接由安卓端进行拦截,然后安卓这边决定是否访问后台数据 还是 本地数据。
https://www.jb51.net/article/129489.htm
思路和如上链接文章中提到的相符,于是参考了其说明的框架方案。生死看淡,说了就干。
安卓端这边使用的离线方案是通过使用三方框架改造的webview以及结合fly.js,将web端的请求通过fly.js进行引擎替换,定向到native。 安卓本地拦截到ajax 请求后,对数据进行解析,然后根据是否是离线模式,决定数据访问后台服务器还是本地数据库。
https://github.com/wendux/DSBridge-Android
https://github.com/wendux/fly
一顿操作猛如虎后,发现问题还是出现在参数格式上,根据fly.js 的说明,其实支持json 和 urlEncode 多种方式传参的,但是在使用urlEncode 方式传参时,碰到了body为空的问题:
AjaxHandler: =====onAjaxRequest requestData={"method":"POST","url":"http:\/\/192.168.65.41:8081\/H5RealMonitor-web\/h5realmonitor\/page\/addH5Page","headers":{"Content-Type":"application\/x-www-form-urlencoded"},"body":"id=110&name=yuanxiaojie.html&alias=yuanxiao&groupId=3234285&type=Android","baseURL":"","timeout":0,"params":{},"parseJson":true,"withCredentials":false}
以上是正常的格式,后来才发现是示例中的参数要做toString处理,这一点是需要注意的。
另外就是json格式的参数在传递时,后台接口对于参数获取的注解需要注意
@RequestParam、@RequestBody和@ModelAttribute区别:
https://www.cnblogs.com/zeroingToOne/p/8992746.html
最终实现了POST he GET 请求以及兼容两种格式传参的功能。
另外,在web端查看sqlite数据的框架方便查看本地数据:
https://github.com/skyhacker2/SQLiteOnWeb-Android