就目前而言,app的开发主要分三个方向:native app、hybrid app以及web app。个人感觉三种app的体验感是逐渐递减的。

hybrid app和web app的开发的不同之处就是前者需要自己提供和实现前端需要的接口,而后者则是借助一些框架(比如icon、dcloud等)。实质上都差不多,但前者更灵活一些。如果你还不知道Hybrid App开发中H5和native如何进行交互,那么相信你看完这篇《Android和H5交互-基础篇》,也行就许明白。

其实H5和native的交互也就那么几个步骤,为了前端能够统一的调用原生提供的接口,通常前端和native(ios和Android)端会做好规范。前面一篇文章主要是介绍两者间是如何进行交互的,那么这篇文章我向大家介绍一种基于两者交互的简单封装。
如果你在为前端写接口时,你可能会这么写:

     /*** dec: js调用原生接口类* createBy yjzhao* createTime 2016/11/15 13:50*/public class NativeApi {/*** 拨打电话** @param mobile 电话号码*/@JavascriptInterfacepublic void openPhone(String mobile) {...}/*** 发短信 一个参数 ISP调用** @param smsto 电话对方电话号码*/@JavascriptInterfacepublic void opneMsg(String smsto) {...}/*** 网络请求代理** @param url  加载的网络URL* @param data 请求的参数* @param jsRe 调用的函数名*/@JavascriptInterfacepublic void reqProxy(String url, String data, String jsRe) {...}/*** 拍照*/@JavascriptInterfacepublic String takePhoto(final String callback) {...}/*** 选择照片*/@JavascriptInterfacepublic String selectPhoto(final String callback) {...}/***  查看图片* @param urls 图片地址(多个图片用,隔开)*/@JavascriptInterfacepublic void browsePhoto(String urls){....}/*** 读取文件** @param url 路径* @return*/@JavascriptInterfacepublic String loadFile(String url) {....}
}

如果是将native接口写成这样的话那么前端js调用的话可能就会是这样:

//拨打电话
NativeAPI.openPhone(params);
//发送短信
NativeAPI.opneMsg(params);
//发送网络请求
NativeAPI.reqProxy(params);
//拍照
NativeAPI.takePhoto(params);
//选择照片
NativeAPI.selectPhoto(params);
//查看照片
NativeAPI.browsePhoto(params);
//读取文件
NativeAPI.loadFile(params);

当然这么写也没问题,但是就觉得麻烦,你觉得呢?

如果你也是这么写Android接口的话,你会发现在维护起来会有些问题的。第一这个类就会变得很臃肿,第二我们知道 js调用Android接口时是运行在一个叫jsBrigde(我没记错的话)的子线程中,而Android调用js方法时是运行在main线程中的,如果需要回调js 方法,这里我们需要做一个线程的切换。如果我们将这个类中的每一个接口方法都独立出去单独写一个类,然后通过统一的接口暴露给前端调用,在调用js方法时统一切换至主线程中,那这样是不是会好一点呢?

那么如何封装呢?我介绍下我的思路:

Android端:

step1 给js暴露一个统一调用的接口sendMessage

 private void addJavascriptInterface(WebView webView) {webView.addJavascriptInterface(new Object(){@JavascriptInterfacepublic void sendMessage(String jsonStr){mHandleJsMessage.handle(jsonStr);}},"native");}

step2 将js传过来的数据进行统一的处理

 /***  处理js传递过来的数据* @param jsonStr js传递的数据* @return 是否处理*/@TargetApi(Build.VERSION_CODES.KITKAT)public  boolean handle(String jsonStr) {JsMessage jsMessage = new Gson().fromJson(jsonStr, JsMessage.class);String action = jsMessage.getAction();jsCallback = jsMessage.getCallback();if (null == jsMessage.getAction())return false;if (HandleAction(jsonStr, action, mActionMap)) return true;return false;}/***  根据js传递过来的action将事件分发下去* @param jsonStr js传递的数据* @param action js意图* @param map js意图集合* @return 是否处理存在处理次意图的接口*/@TargetApi(Build.VERSION_CODES.KITKAT)private boolean HandleAction(String jsonStr, String action, Map<String, Class<? extends JsAction>> map) {for (String mapAction : map.keySet()) {if (mapAction.equals(action)) {try {mJsAction = map.get(mapAction).newInstance();if (mJsAction != null) {mJsAction.handleAction(mContext, jsonStr);}} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}return true;}}return false;}

step3 将线程切换至主线程并将处理结果返回前端

public void callback(final WebView webView, final String callback, final Object result){//切换至主线程Observable.create(new ObservableOnSubscribe<Object>() {@Overridepublic void subscribe(ObservableEmitter<Object> emitter) throws Exception {emitter.onNext("");}}).subscribeOn(Schedulers.trampoline())//作用是在当前线程中立即执行任务.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Object>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Object o) {if (null==result || null==callback || "".equals(callback))return;String resultStr= new Gson().toJson(result);String url = "javascript:" + callback + "("+resultStr+")";webView.loadUrl(url);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});
}

这个三个步骤就是核心思路,具体的实现就不在这贴代码了,感兴趣的可以查看源码,地址文末会给出。
再看下 前端js怎么封装:

  ///
//      调用原生接口      //
///
;(function($) {
"use strict"//使用严格模式function native(params) {params = params||{};if (params==="undefind")return;if (params.action==="undefind")return;//固定的三个属性和native端一样,否则native端和解析出错var Senddata={action:params.action,callback:"nativeCallback",data:params.data,}window.nativeCallback = function(data) {if (params.callback!=="undefind") {params.callback(data);}}var sendDataStr=JSON.stringify(Senddata);window.native.sendMessage(sendDataStr);}$.native = native;
})($);

这段代码是不是很简单,值得注意的是js传给native的json数据格式是固定的:即

{"action":"action","callback":"nativeCallback","data":{这里的数据格式和native端的处理action实现类数据格式需协商一致}
}

how to use?

android端:

  compile 'com.zyj:hybridbridge:0.1.0'//添加依赖

1、首先在activity中初始化

JsBridge.getInstance().init(this, webView)

2、然后为添加需要处理的action以及相应的处理类

JsBridge.getInstance().addJsAction(JsDeviceInfo.ACTION, JsDeviceInfo.class);//JsDeviceInfo的写法实例(这个类需继承JsAction这个抽象类并实现handleAction()方法)
public class JsDeviceInfo extends JsAction {//这个action需和前端相对应
public static final String ACTION = "deviceinfo";@Override
protected void handleAction(Activity context, String jsonStr) {HandleResult resultEntity =new HandleResult();DeviceInfoEntity deviceInfoEntity =new DeviceInfoEntity();deviceInfoEntity.setDeviceName("我的Android客户端!");resultEntity.setData(deviceInfoEntity);//处理完相关业务之后将结果发送出去,post之后会自动调用js的callback方法RxBus.getInstance().post(resultEntity);}
}

前端:

  function callback(backdata) {//native处理完后会回调用这个方法}$.native({action: "deviceinfo",callback: callback});

看完之后是不是觉得不管是前端还是native端都很简单?所有的action以及传递的参数格式都可以自定义,只需保证两端统一即可。
如果你感兴趣,源码在这HybridBridge,欢迎start,有什么问题可以留言我会维护改进的。

作者:Jesse_zhao
链接:https://www.jianshu.com/p/02afb387b6b4
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android 和H5之间的交互-框架篇相关推荐

  1. Android 和 H5 交互-框架篇

    Android 和 H5 交互-框架篇 2017-08-01 YouJZ code小生 作者 | YouJZ 地址 | http://www.jianshu.com/p/02afb387b6b4 声明 ...

  2. 相同点安卓和iosui的相同点_9个Android和iOS之间的交互差异点

    9个Android和iOS之间的交互差异点 十一月 8, 2019 发表于: 交互设计. 评论 Sponsor 移动端开发的主要载体是Android和iOS,在开发的时候出于某些原因而采用一套设计方案 ...

  3. Android内部h5和native交互实现方式

    Android具体实现方式 一.实现方式 a.h5调用native: Android实现h5到native的方式为截获h5调用的特定url,一般url都是http://**这种,为了能够捕获h5调用的 ...

  4. Android 系统(229)---Android与h5交互专题

    [Android开发进阶系列]Android与h5交互专题 1 交互原理 1.1 webview如何加载H5页面 我们都知道在Android中是通过webView来加载html页面的,根据HTML文件 ...

  5. Android和H5交互-基础篇

    hybrid App开发也不是什么新鲜事了,其中native和h5之间的交互则是必不可少的.Android中是如何和H5交互的? 1.webView加载页面 我们都知道在Android中是通过webV ...

  6. android js交互 数组,Android WebView —— Java 与 JavaScript 交互总结

    相比于 Native App 和 Web App,Hybrid App 凭借其迭代灵活.控制自如.多端同步的优势在应用市场上越发显得优胜,主要得力于,其将变更频繁的部分产品功能使用 H5 开发并在客户 ...

  7. Hybrid框架之交互通信篇

    前言 虽然有些应用在使用React Native或Weex开发,但综合来看,业内还是以混合开发模式为主,从我们自家的App来看,H5业务所占比重越来越高,目前大概占到35%左右,因此一套好的Hybri ...

  8. android h5 书,android与H5交互

    1 - WebView基本配置 2 -WebView和H5的交互 3 - WebView错误页面处理 4 -WebView中的Cookie操作 5 -WebView漏洞 6 -WebView内存泄漏问 ...

  9. android前端怎样php后台交互(基础篇)

    android前端怎样php后台交互(基础篇) android客户端和php+mysql+apache搭建的服务器之间的简单交互,实现登入功能. 实现原理就是android客户端发送请求,传给服务器登 ...

最新文章

  1. GNU/Linux下LVM配置管理以及快照卷、物理卷、卷组、逻辑卷的创建和删除
  2. 为了追求极致的性能,Kafka掌控这11项要领
  3. java.lang.IllegalArgumentException 严重: Context initialization failed
  4. try-catch 异常处理的执行过程
  5. 订单生产计划表范本_生产计划表_用Excel 如何制作生产排单的生产计划
  6. php tcpdf 没有头部,TCPDF - 设置头部Logo不显示问题
  7. 代理 傲澜智伴机器人_机器人厂家_智伴机器人代理,莆田智伴机器人,傲澜智伴机器人(查看)_一呼百应网...
  8. 关于Oracle的PARALLEL MAX SEVERS参数
  9. Aptana工具介绍
  10. 龙芯linux内核空间内存划分,最强龙芯+最新内核+最大内存
  11. 计算机系微电子专业大学排名,2017微电子专业大学排名
  12. 基于Android的聊天系统
  13. ESD静电二极管|静电保护器件
  14. 文科高中毕业学计算机技术,一位高中生的困惑:成绩好的学理科,成绩差的学文科?...
  15. Win7开启无线热点AP
  16. Strategy模式的具体实现
  17. 独享服务器做系统,独享服务器的含义与好处
  18. 标签稀疏类别不平衡问题解决方案总结
  19. 无聊之作——《随机组句》
  20. 【吴恩达深度学习week4编程作业】

热门文章

  1. python中属性赋值查找_关于python:在dataframe列中查找字典的值并进行修改
  2. 怎么编辑图片尺寸?如何编辑照片大小?
  3. 如何使用oracle修改表字段长度
  4. Android中创建Surface和TYPE_WALLPAPER类型的window
  5. 杨辉三角java实验目的,杨辉三角java
  6. PLC笔记(一)PLC入门姿势
  7. 易用性测试及GUI常见的测试要求
  8. 【元胞自动机】元胞自动机模拟SEIR传播模型和采取隔离措施的SEIR模型【含Matlab源码 2181期】
  9. Scratch 游戏项目学习法 —— 接苹果(七)让苹果回到顶部
  10. 第十二届蓝桥杯省赛详解