{"id":13639224,"url":"https://github.com/wendux/DSBridge-Android","last_synced_at":"2025-04-19T22:31:54.312Z","repository":{"id":37390884,"uuid":"77830426","full_name":"wendux/DSBridge-Android","owner":"wendux","description":":earth_americas: A modern cross-platform JavaScript bridge, through which you can invoke each other's functions synchronously or asynchronously between JavaScript and native.","archived":false,"fork":false,"pushed_at":"2020-09-11T06:36:58.000Z","size":902,"stargazers_count":3771,"open_issues_count":105,"forks_count":617,"subscribers_count":94,"default_branch":"master","last_synced_at":"2024-11-05T05:22:17.258Z","etag":null,"topics":["javascript-bridge","jsbridge","support-x5","webviewjavascriptbridge"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wendux.png","metadata":{"files":{"readme":"readme-chs.md","changelog":"changelist.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-02T11:58:53.000Z","updated_at":"2024-11-02T14:44:24.000Z","dependencies_parsed_at":"2022-07-14T09:22:34.660Z","dependency_job_id":null,"html_url":"https://github.com/wendux/DSBridge-Android","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wendux%2FDSBridge-Android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wendux%2FDSBridge-Android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wendux%2FDSBridge-Android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wendux%2FDSBridge-Android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wendux","download_url":"https://codeload.github.com/wendux/DSBridge-Android/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223810303,"owners_count":17206732,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript-bridge","jsbridge","support-x5","webviewjavascriptbridge"],"created_at":"2024-08-02T01:00:58.771Z","updated_at":"2024-11-09T09:30:44.039Z","avatar_url":"https://github.com/wendux.png","language":"Java","readme":"# DSBridge for Android\n\n![dsBridge](https://github.com/wendux/DSBridge-IOS/raw/master/img/dsbridge.png)\n\n[![](https://jitpack.io/v/wendux/DSBridge-Android.svg)](https://jitpack.io/#wendux/DSBridge-Android)\n![language](https://img.shields.io/badge/language-Java-yellow.svg)\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://opensource.org/licenses/mit-license.php)\n[![](https://travis-ci.org/wendux/DSBridge-Android.svg?branch=master)](https://travis-ci.org/wendux/DSBridge-Android)\n[![GitHub last commit](https://img.shields.io/github/last-commit/wendux/DSBridge-Android.svg?color=blue)](https://github.com/wendux/DSBridge-Android/tree/master)\n![](https://img.shields.io/badge/minSdkVersion-11-yellow.svg)\n[![x5](https://img.shields.io/badge/support%20x5-yes-blue.svg)](https://github.com/wendux/DSBridge-Android/tree/x5-3.0)\n\n\u003e 三端易用的现代跨平台 Javascript bridge， 通过它，你可以在Javascript和原生之间同步或异步的调用彼此的函数.\n\n\n### 注意\n\nDSBridge v3.0 是一个里程碑版本，和v2.0相比，有许多变化，需要注意的是v3.0**不兼容**之前版本，但是我们也会继续维护v2.0分支，所以，如果你是v2.0的使用者，请放心继续使用v2.0，如果你是新用户，请使用\u003e=v3.0.\n\n[DSBridge v3.0.0 更新列表](https://github.com/wendux/DSBridge-Android/issues/31)  \n腾讯X5内核支持：https://github.com/wendux/DSBridge-Android/tree/x5-3.0\n\n\n## 特性\n\n1. Android、IOS、Javascript 三端易用，轻量且强大、安全且健壮。\n\n2. 同时支持同步调用和异步调用\n\n3. 支持以类的方式集中统一管理API\n\n4. 支持API命名空间\n\n5. 支持调试模式\n\n6. 支持API存在性检测\n\n7. 支持进度回调：一次调用，多次返回\n\n8. 支持Javascript关闭页面事件回调\n\n9. 支持Javascript 模态/非模态对话框\n\n10. 支持腾讯X5内核\n\n  ​\n\n## 安装\n\n1. 添加 JitPack repository 到gradle脚本中\n\n   ```groovy\n   allprojects {\n     repositories {\n      ...\n      maven { url 'https://jitpack.io' }\n     }\n   }\n   ```\n\n2. 添加依赖\n\n   ```groovy\n   dependencies {\n   \t//compile 'com.github.wendux:DSBridge-Android:3.0-SNAPSHOT'\n   \t//support the x5 browser core of tencent\n   \t//compile 'com.github.wendux:DSBridge-Android:x5-3.0-SNAPSHOT'\n   }\n   ```\n\n## 示例\n\n请参考工程目录下的 `wendu.jsbdemo/` 包。运行 `app` 工程并查看示例交互。\n\n如果要在你自己的项目中使用 dsBridge :\n\n## 使用\n\n1.  新建一个Java类，实现API\n\n   ```java\n   public class JsApi{\n       //同步API\n       @JavascriptInterface\n       public String testSyn(Object msg)  {\n           return msg + \"［syn call］\";\n       }\n\n       //异步API\n       @JavascriptInterface\n       public void testAsyn(Object msg, CompletionHandler\u003cString\u003e handler) {\n           handler.complete(msg+\" [ asyn call]\");\n       }\n   }\n   ```\n\n   可以看到，DSBridge正式通过类的方式集中、统一地管理API。由于安全原因，所有Java API 必须有\"@JavascriptInterface\" 标注。\n\n2. 添加API类实例到 DWebView .\n\n   ```javascript\n   import wendu.dsbridge.DWebView\n   ...\n   DWebView dwebView= (DWebView) findViewById(R.id.dwebview);\n   dwebView.addJavascriptObject(new JsApi(), null);\n   ```\n\n3. 在Javascript中调用原生 (Java/Object-c/swift) API ,并注册一个 javascript API供原生调用.\n\n   - 初始化 dsBridge\n\n     ```javascript\n     //cdn方式引入初始化代码(中国地区慢，建议下载到本地工程)\n     //\u003cscript src=\"https://unpkg.com/dsbridge@3.1.3/dist/dsbridge.js\"\u003e \u003c/script\u003e\n     //npm方式安装初始化代码\n     //npm install dsbridge@3.1.3\n     var dsBridge=require(\"dsbridge\")\n     ```\n\n   - 调用原生API ,并注册一个 javascript API供原生调用.\n\n     ```javascript\n\n     //同步调用\n     var str=dsBridge.call(\"testSyn\",\"testSyn\");\n\n     //异步调用\n     dsBridge.call(\"testAsyn\",\"testAsyn\", function (v) {\n       alert(v);\n     })\n\n     //注册 javascript API \n      dsBridge.register('addValue',function(l,r){\n          return l+r;\n      })\n     ```\n\n4. 在Java中调用 Javascript API \n\n   ```java\n   dwebView.callHandler(\"addValue\",new Object[]{3,4},new OnReturnValue\u003cInteger\u003e(){\n        @Override\n        public void onValue(Integer retValue) {\n           Log.d(\"jsbridge\",\"call succeed,return value is \"+retValue);\n        }\n   });\n   ```\n\n\n\n\n## Java API 签名\n\n为了兼容IOS，我们约定 Java API 签名，**注意，如果API签名不合法，则不会被调用**！签名如下：\n\n1. 同步API.\n\n   **` public any handler(Object msg) `**\n\n   参数必须是 `Object` 类型，**并且必须申明**（如果不需要参数，申明后不适用即可）。返回值类型没有限制，可以是任意类型。\n\n2. 异步 API.\n\n   **`public void handler(Object arg, CompletionHandler handler)`**\n\n\n\n## 命名空间\n\n命名空间可以帮助你更好的管理API，这在API数量多的时候非常实用，比如在混合应用中。DSBridge (\u003e= v3.0.0) 支持你通过命名空间将API分类管理，并且命名空间支持多级的，不同级之间只需用'.' 分隔即可。\n\n\n\n## 调试模式\n\n在调试模式时，发生一些错误时，将会以弹窗形式提示，并且原生API如果触发异常将不会被自动捕获，因为在调试阶段应该将问题暴露出来。如果调试模式关闭，错误将不会弹窗，并且会自动捕获API触发的异常，防止crash。强烈建议在开发阶段开启调试模式，可以通过如下代码开启调试模式\n\n```java\nDWebView.setWebContentsDebuggingEnabled(true)\n```\n\n\n\n## 进度回调\n\n通常情况下，调用一个方法结束后会返回一个结果，是一一对应的。但是有时会遇到一次调用需要多次返回的场景，比如在javascript钟调用端上的一个下载文件功能，端上在下载过程中会多次通知javascript进度, 然后javascript将进度信息展示在h5页面上，这是一个典型的一次调用，多次返回的场景，如果使用其它Javascript bridge,  你将会发现要实现这个功能会比较麻烦，而DSBridge本省支持进度回调，你可以非常简单方便的实现一次调用需要多次返回的场景，下面我们实现一个倒计时的例子：\n\nIn Java \n\n```java\n@JavascriptInterface\npublic void callProgress(Object args, final CompletionHandler\u003cInteger\u003e handler) {\n    new CountDownTimer(11000, 1000) {\n        int i=10;\n        @Override\n        public void onTick(long millisUntilFinished) {\n            //setProgressData can be called many times util complete be called.\n            handler.setProgressData((i--));\n        }\n        @Override\n        public void onFinish() {\n           //complete the js invocation with data; \n           //handler will invalid when complete is called\n            handler.complete(0);\n        }\n    }.start();\n}\n```\n\nIn Javascript\n\n```javascript\ndsBridge.call(\"callProgress\", function (value) {\n    document.getElementById(\"progress\").innerText = value\n})\n```\n\n完整的示例代码请参考demo工程。\n\n\n\n## Javascript 弹出框\n\nDSBridge已经实现了 Javascript的弹出框函数(alert/confirm/prompt)，如果你想自定义它们，通过`WebChromeClient`重写相关函数即可。DSBridge实现的对话框默认设置是模态的，这会挂起UI线程，如果你需要非模态对话框，请参考`dwebview.disableJavascriptDialogBlock(bool disable)` 。\n\n\n\n## 安全\n\n在Android 4.2(API17)之前 `webview.addJavascriptInterface` 存在安全漏洞，DSBridge内部在4.2以下的设备上不会使用` webview.addJavascriptInterface`，而是通过其它方式通信，在4.2之后会使用 `webview.addJavascriptInterface` 。同时，为了防止Javascript调用未授权的原生函数，所有Java API 必须有\"@JavascriptInterface\" 标注，所以在任何版本的Android系统下，您可以放心使用DSBridge！\n\n\n\n## DWebView\n\nDWebView中，如果在非主线程调用下列方法时，它们内部会自动分发到主线程中执行，你再也无需手动切换。\n\n```java\nvoid loadUrl( String url) \nvoid loadUrl( String url, Map\u003cString, String\u003e additionalHttpHeaders)\nvoid evaluateJavascript(String script) \n```\n\n\n\n## API 列表\n\n### Java API\n\n在Java中我们把实现了供 javascript调用的 API类的实例 成为 **Java API object**.\n\n##### `dwebview.addJavascriptObject(Object object, String namespace)`\n\n添加一个Java API object到DWebView ，并为它指定一个命名空间。然后，在 javascript 中就可以通过`bridge.call(\"namespace.api\",...)`来调用Java API object中的原生API了。\n\n如果命名空间是空(null或空字符串）, 那么这个添加的  Java API object就没有命名空间。在 javascript 通过 `bridge.call(\"api\",...)`调用。\n\n**示例**:\n\nIn Java\n\n```javascript\npublic class JsEchoApi {\n    @JavascriptInterface\n    public Object syn(Object args) throws JSONException {\n        return  args;\n    }\n\n    @JavascriptInterface\n    public void asyn(Object args,CompletionHandler handler){\n        handler.complete(args);\n    }\n}\n//namespace is \"echo\"\ndwebView.addJavascriptObject(new JsEchoApi(),\"echo\");\n```\n\nIn Javascript\n\n```javascript\n// call echo.syn\nvar ret=dsBridge.call(\"echo.syn\",{msg:\" I am echoSyn call\", tag:1})\nalert(JSON.stringify(ret))  \n// call echo.asyn\ndsBridge.call(\"echo.asyn\",{msg:\" I am echoAsyn call\",tag:2},function (ret) {\n      alert(JSON.stringify(ret));\n})\n```\n\n\n\n##### `dwebview.removeJavascriptObject(String namespace)`\n\n通过命名空间名称移除相应的Java API object 。\n\n\n\n##### `dwebview.callHandler(String handlerName, Object[] args)`\n\n##### `dwebview.callHandler(String handlerName, OnReturnValue handler)`\n\n##### `dwebview.callHandler(String handlerName, Object[] args,OnReturnValue handler)`\n\n调用 javascript API。`handlerName`  为javascript API 的名称，可以包含命名空间；参数以数组传递，`args`数组中的元素依次对应javascript API的形参； `handler` 用于接收javascript API的返回值，**注意：handler将在主线程中被执行**。\n\n示例:\n\n```java\n\ndWebView.callHandler(\"append\",new Object[]{\"I\",\"love\",\"you\"},new OnReturnValue\u003cString\u003e((){\n    @Override\n    public void onValue(String retValue) {\n        Log.d(\"jsbridge\",\"call succeed, append string is: \"+retValue);\n    }\n});\n// call with namespace 'syn', More details to see the Demo project                    \ndWebView.callHandler(\"syn.getInfo\", new OnReturnValue\u003cJSONObject\u003e() {\n    @Override\n    public void onValue(JSONObject retValue) {\n      showToast(retValue);\n    }\n});\n```\n\n\n\n##### `dwebview.disableJavascriptDialogBlock(bool disable)`\n\n**小心使用**. 如果你在javascript中调用弹窗函数(`alert`,` confirm`, 或 `prompt`)， 那么APP将会挂起，因为这些弹窗都是**模态**的，会阻塞APP主线程，此时javascript执行流也会阻塞。如果你想避免阻塞，可以通过此API禁止，禁止后，一旦 javascript中调用了这些弹窗函数，APP将弹出**非模态**对话框，并立即返回，(  `confirm` 会返回 `true`,  `prompt` 返回空字符串)。\n\n禁止Javascript对话框阻塞:\n\n```javascript\ndwebview.disableJavascriptDialogBlock(true);\n```\n\n如果你想恢复**模态**对话框，传 `false` 调用即可.\n\n\n\n##### `dwebview.setJavascriptCloseWindowListener(JavascriptCloseWindowListener listener)`\n\n当 Javascript中调用`window.close`时，DWebView会触发此监听器，如果未设置，DWebView默认会关闭掉当前Activity. \n\nExample:\n\n```java\ndwebview.setJavascriptCloseWindowListener(new DWebView.JavascriptCloseWindowListener() {\n    @Override\n    public boolean onClose() {\n        Log.d(\"jsbridge\",\"window.close is called in Javascript\");\n        //如果返回false,则阻止DWebView默认处理. \n        return false;\n    }\n});\n```\n\n\n\n##### `dwebview.hasJavascriptMethod(String handlerName, OnReturnValue\u003cBoolean\u003e existCallback)`\n\n检测是否存在指定的 javascript API，`handlerName`可以包含命名空间. \n\n示例:\n\n```java\n dWebView.hasJavascriptMethod(\"addValue\", new OnReturnValue\u003cBoolean\u003e() {\n    @Override\n    public void onValue(Boolean retValue) {\n     showToast(retValue);\n    }\n });\n```\n\n\n\n##### `DWebView.setWebContentsDebuggingEnabled(boolean enabled)`\n\n设置调试模式。在调试模式时，发生一些错误时，将会以弹窗形式提示，并且原生API如果触发异常将不会被自动捕获，因为在调试阶段应该将问题暴露出来。如果调试模式关闭，错误将不会弹窗，并且会自动捕获API触发的异常，防止crash。强烈建议在开发阶段开启调试模式。\n\n\n\n### Javascript API\n\n##### dsBridge \n\n\"dsBridge\" 在初始化之后可用 .\n\n##### `dsBridge.call(method,[arg,callback])`\n\n同步或异步的调用Java API。\n\n`method`: Java API 名称， 可以包含命名空间。\n\n`arg`:传递给Java API 的参数。只能传一个，如果需要多个参数时，可以合并成一个json对象参数。\n\n`callback(String returnValue)`: 处理Java API的返回结果. 可选参数，**只有异步调用时才需要提供**.\n\n\n\n##### `dsBridge.register(methodName|namespace,function|synApiObject)`\n\n##### `dsBridge.registerAsyn(methodName|namespace,function|asynApiObject)`\n\n注册同步/异步的Javascript API. 这两个方法都有两种调用形式：\n\n1. 注册一个普通的方法，如:\n\n   In Javascript\n\n   ```javascript\n   dsBridge.register('addValue',function(l,r){\n        return l+r;\n   })\n   dsBridge.registerAsyn('append',function(arg1,arg2,arg3,responseCallback){\n        responseCallback(arg1+\" \"+arg2+\" \"+arg3);\n   })\n   ```\n\n   In Java\n\n   ```java\n   webView.callHandler(\"addValue\",new Object[]{1,6},new OnReturnValue\u003cString\u003e(){\n     @Override\n     public void onValue(String retValue) {\n       Log.d(\"jsbridge\",\"call succeed,return value is: \"+retValue);\n     }\n   });\n\n   webView.callHandler(\"append\",new Object[]{\"I\",\"love\",\"you\"},new OnReturnValue\u003cString\u003e(){\n      @Override\n      public void onValue(String retValue) {\n        Log.d(\"jsbridge\",\"call succeed, append string is: \"+retValue);\n      }\n   });\n   ```\n\n   ​\n\n2. 注册一个对象，指定一个命名空间:\n\n   **In Javascript**\n\n   ```javascript\n   //namespace test for synchronous calls\n   dsBridge.register(\"test\",{\n     tag:\"test\",\n     test1:function(){\n   \treturn this.tag+\"1\"\n     },\n     test2:function(){\n   \treturn this.tag+\"2\"\n     }\n   })\n     \n   //namespace test1 for asynchronous calls  \n   dsBridge.registerAsyn(\"test1\",{\n     tag:\"test1\",\n     test1:function(responseCallback){\n   \treturn responseCallback(this.tag+\"1\")\n     },\n     test2:function(responseCallback){\n   \treturn responseCallback(this.tag+\"2\")\n     }\n   })\n   ```\n\n   \u003e 因为Javascript并不支持函数重载，所以不能在同一个Javascript对象中定义同名的同步函数和异步函数\n\n   **In Java**\n\n   ```java\n   webView.callHandler(\"test.test1\",new OnReturnValue\u003cString\u003e(){\n       @Override\n       public void onValue(String retValue) {\n           Log.d(\"jsbridge\",\"Namespace test.test1: \"+retValue);\n       }\n   });\n\n   webView.callHandler(\"test1.test1\",new OnReturnValue\u003cString\u003e(){\n       @Override\n       public void onValue(String retValue) {\n           Log.d(\"jsbridge\",\"Namespace test.test1: \"+retValue);\n       }\n   });\n   ```\n\n\n\n\n##### `dsBridge.hasNativeMethod(handlerName,[type])`\n\n检测Java中是否存在名为`handlerName`的API, `handlerName` 可以包含命名空间. \n\n`type`: 可选参数，`[\"all\"|\"syn\"|\"asyn\" ]`, 默认是 \"all\".\n\n```javascript\n//检测是否存在一个名为'testAsyn'的API(无论同步还是异步)\ndsBridge.hasNativeMethod('testAsyn') \n//检测test命名空间下是否存在一个’testAsyn’的API\ndsBridge.hasNativeMethod('test.testAsyn')\n// 检测是否存在一个名为\"testSyn\"的异步API\ndsBridge.hasNativeMethod('testSyn','asyn') //false\n```\n\n\n\n##### `dsBridge.disableJavascriptDialogBlock(disable)`\n\n调用 `dsBridge.disableJavascriptDialogBlock(...)` 和在Java中调用 `dwebview.disableJavascriptDialogBlock(...)` 作用一样.\n\n示例:\n\n```javascript\n//disable\ndsBridge.disableJavascriptDialogBlock()\n//enable\ndsBridge.disableJavascriptDialogBlock(false)\n```\n\n\n\n## 和 fly.js一起使用\n\n当dsBridge遇见  [Fly.js](https://github.com/wendux/fly)  时，将会打开一个新的世界。[fly.js传送门](https://github.com/wendux/fly)\n\n正如我们所知，在浏览器中，ajax请求受同源策略限制，不能跨域请求资源。然而，  [Fly.js](https://github.com/wendux/fly) 有一个强大的功能就是支持请求重定向：将ajax请求通过任何Javascript bridge重定向到端上，并且 [Fly.js](https://github.com/wendux/fly) 官方已经提供的 dsBridge 的 adapter, 可以非常方便的协同dsBridge一起使用。由于端上没有同源策略的限制，所以 fly.js可以请求任何域的资源。\n\n另一个典型的使用场景是在混合APP中，由于[Fly.js](https://github.com/wendux/fly) 可以将所有ajax请求转发到端上，所以，开发者就可以在端上进行统一的请求管理、证书校验、cookie管理、访问控制等。\n\n具体的示例请查看demo.\n\n## 最后\n\n如果你喜欢DSBridge, 欢迎star，以便更多的人知道它, 谢谢 !\n","funding_links":[],"categories":["WebView","Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwendux%2FDSBridge-Android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwendux%2FDSBridge-Android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwendux%2FDSBridge-Android/lists"}