• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 【Android】如何写一个JsBridge

【Android】如何写一个JsBridge

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android jsbridge,jsbridge,jsbridge.jar,jsbridge是什么,jsbridge tracelog等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

【Android】如何写一个JsBridge


JsBridge

简介

Android JsBridge 就是用来在 Android app的原生 java 代码与 javascript 代码中架设通信(调用)桥梁的辅助工具。

原理概述

Javascript 运行在 WebView 中,而 WebView 只是 Javascript 执行引擎与页面渲染引擎的一个包装而已。

由于这种天然的隔离效应,我们可以将这种情况与 IPC 进行类比,将 Java 与 Javascript 的每次互调都看做一次 IPC 调用。
如此一来,我们可以模仿各种已有的 IPC 方式来进行设计,比如 RPC。本文模仿 Android 的 Binder 机制来实现一个 JsBridge。

首先回顾一一下基于 Binder 的经典 RPC 调用:

Javascript-bridge-rpc

当然,client 与 server 只是用来区分通信双方责任的叫法而已,并不是一成不变的。
对于 java 与 javascript 互调的情况,当 java 主动调用 javascript 的时候,java 充当 client 角色,javascript 则扮演 server 的角色,
javascript 中的函数执行完毕后回调 java 方法,这个时候,javascript 充当 client 角色,而 javascript 则承担 server 的责任。<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="Javascript-bridge-circle" src="http://www.bkjia.com/uploads/allimg/160414/0423011a3-1.png" title="\" />

剩下的问题就是怎么来实现这个机制了,大致有这么几个需要解决的问题:

java 如何调用 Javascript Javascript 如何调用 java 方法参数以及回调如何处理通信的数据格式是怎样的

下面逐个讨论这些问题:

1. java 如何调用 Javascript

要实现 Java 与 Javascript 的相互调用,有两条途径可以考虑:

集成一个定制化的 Javascript 与 Html 渲染引擎,java 通过引擎底层与 Javascript 交互。这样可以获得完全的控制权。使用 Android Sdk 提供的交互方法。

对于第一种途径,代价比较大,而且技术方案比较复杂,一般只有基于 Javascript 的跨平台开发方案才会这么做。
所以,现在着重考查第二种途径。

Android 的默认 Sdk 中, Java 与 Javascript 的一切交互都是依托于 WebView 的,大致有以下几个可用方法:

第一, Java 调用 Javascript 方法
    webView.loadUrl("javascript:scriptString"); //其中 scriptString 为 Javascript 代码

在 KITKAT 之后,又新增了一个方法:

    webView.evaluateJavascript(scriptString, new ValueCallback() {
        @Override
        public void onReceiveValue(String value) {
        }
    });//其中 scriptString 为 Javascript 代码,ValueCallback 的用来获取 Javascript 的执行结果。这是一个异步掉用。

这个调用看起比上面的正常,而且更像是一个方法调用。

需要注意的是,ValueCallback 并不是在 UI 线程里面执行的。

2. Javascript 如何调用 java

要实现 Javascript 调用 java 方法,需要先在 Javascript 环境中注入一个 Java 代理:


    class JavaProxy{
        @JavascriptInterface //注意这里的注解。出于安全的考虑,4.2 之后强制要求,不然无法从 Javascript 中发起调用
        public void javaFn(){
            //xxxxxx
        };
    }
    webView.addJavascriptInterface(new JavaProxy();, "java_proxy");

然后在 Javascript 环境中直接调用 obj_proxy 代理上的方法即可。


    java_proxy.javaFn();

这里有两个方面需要统一:

Javascript 的执行方法比较怪异,所以,我们需要将概念统一化。如果需要执行的方法比较多,那么,代理对象上也需要定义非常多的方法,我们需要将各种方法定义统一起来管理。

所以,我们先将 Javascript 的执行包装成类似 java 一样的代理对象,然后通过在各自的 stub 上注册回调来增加功能支持。
比如,如果 java 想增加 getPackageName 方法,那么,直接在 JavaProxy 上注册即可:


    javaProxy.register("getPackageName", new JavaHandler(){
        @Override
        public void handle(Object value){
            //xxxxx
        }
    })

如图:

Javascript-bridge-register

3. 方法参数以及回调如何处理

很显然,任何 IPC 通信都涉及到参数序列化的问题, 同理 java 与 Javascript 之间只能传递基础类型(注意,不单纯是基本类型),包括基本类型与字符串,不包括其他对象或者函数。
由于只涉及到简单的相互调用,这里就可以考虑采用 JSON 格式来传递各种数据,轻量而简洁。

Java 调用 Javascript 没有返回值(这里指 loadUrl 形式的调用),因此如果 java 端想从 Javascript 中获取返回值,只能使用回调的形式。
但是在执行完毕之后如何找到正确的回调方法信息,这是一个重要的问题。比如有下面的例子:

在 java 环境中,JavaProxy 对象有一个无参数的 getPackageName 方法用来获取当前应用的 PackageName。
获取到 packageName 之后,传递给 Javascript 调用者的对应回调中。

在 Javascript 环境中,获取当前应用的 PackageName 的大致调用如下:

    bridge.invoke('getPackageName', null, function(packageName){
        console.log(packageName);
    });
````
显然


 </div> ```javascript function(packageName){ console.log(packageName); }

这个 Javascript 函数是无法传递到 java 环境中的,所以,可以采取的一个策略就是,
在 Javascript 环境中将所有回调统一管理起来,而只是将回调的 id 传递到 java 环境去,java 方法执行完毕之后,
将回调参数以及对应的回调 id 返回给 Javascript 环境,由 Javascript 来负责执行正确的回调。

这样,我们就可以实现一个简单的回调机制:

在 java 环境中


    class JavaProxy{
        public void onTransact(String jsonInvoke, String jsonParam){
            json = new Json(jsonInvoke);
            invokeName = json.getInvokeName(); // getPackageName
            callbackId = json.getCallbackId(); // 12345678xx
            invokeParam = new Param(jsonParam);// null
            ...
            ...
            JsProxy.invoke(callbackId, callbackParam); //发起 Javascript 调用,让 Javascript 去执行对应的回调
        }
    }

在 javascript 环境中


    bridge.invoke = function(name, param, callback){
        var callbackId = new Date().getTime();
        _callbacks[callbackId] = callback;
        var invoke = {
            "invokeName" : name,
            "callbackId" : callbackId
        };
        JavaProxy.onTransact(JSON.stringify(invoke), JSON.stringify(param));
    }
     bridge.invoke('getPackageName', null, function(packageName){
         console.log(packageName);
     });  

反之亦然。

4. 通信的数据格式是怎样的

问题都处理了,只需要设计对应的协议即可。
按照上面的讨论,

在 client 端:

我们使用

    Proxy.transact(invoke, callback);

来调用 server 端注册的方法。

在 server 端

我们使用

    Stub.register(name, handler);

来注册新功能,使用

    Stub.onTransact(invoke, handler);

来处理接收到的 client 端调用。

其中,invoke 包含所要执行的方法以及回调的信息,因此,invoke 的设计如下:

{
    _invoke_id : 1234,  
    _invoke_name : "xxx",  
    _callback_id : 5678,  
    _callback_name : "xxx"  
}

注意 _invoke_id 与 _invoke_name 的区别:

如果当前 invoke 是一个直接方法调用,那么 _invoke_id 应该是无效的。
如果当前 invoke 是一个回调,那么 _invoke_id + _invoke_name 共同决定回调的具体对象

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 【Android】如何写一个JsBridge
  • Android JSBridge的原理与实现

相关文章

  • 2017-05-26Android实战技巧之四十八:Android上的Java8和kotlin
  • 2017-05-26Android学习--RelativeLayout相对布局
  • 2017-05-26Android之文件数据存储,android数据存储
  • 2017-05-26安卓开源项目周报0215,安卓开源项目0215
  • 2017-05-26滑动关闭activity,滑动activity
  • 2017-05-26安卓自定义组合控件--toolbar,安卓控件--toolbar
  • 2017-05-26【转载】ReactiveX 的理念和特点,转载reactivex理念
  • 2017-05-26Android实战技巧之五十:App的系统签名
  • 2017-10-21使用AndroidStudio建立简单的单元测试
  • 2017-05-26AppLaunchChecker

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • andriod绘制图形,andriod绘制
    • Android合并两个APP的具体做法(掌握)
    • Android基于监听的事件处理机制
    • arcgis andriod 加载影像,arcgisandriod
    • android StringBuffer 和StringBuilder,androidstringbuffer
    • android应用开发-从设计到实现3-8静态原型的Appbar折叠
    • Android开发学习之路--图表实现(achartengine/MPAndroidChart)之初体验
    • 不带数据和返回的Activity跳转,返回activity跳转
    • Android第一天--&gt;布局,android第一天--
    • Android事件分发机制浅谈(一),android浅谈

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有