Git Product home page Git Product logo

jsbridge's Introduction

English | 简体中文

JsBridge

A simpler, extendable bidirectional communication Frame between Android WebView and Javascript

Features

  • supports parsing and callback for JS primitive types
  • Modular management
  • support System WebView and Custom WebView
  • permission authentication is implemented by Native, JS do not need to depend other file
  • support Android API 8+, avoid addJavascriptInterface Vulnerability
  • compatible with iOS WebViewJavascriptBridge

Getting Started

Download the latest JAR or Gradle:

compile 'com.apkfuns.jsbridge:jsbridge:2.1.1'

The library dependen on support-annotations, if your project already exists, please exclude

compile('com.apkfuns.jsbridge:jsbridge:2.1.1') {
    exclude module: 'support-annotations'
}

Examples

We use JS to call the original module to achieve ajax cross-domain request to briefly introduce the use of the library

1.Create Module

Create a module that needs to inherit JsModule and implement thegetModuleNamemethod, the module naming request is the same as the java variable naming, must not be empty, only allow underline(_) LettersNumber, if is static Module (not contain module name),need to inherit JsStaticModule, the following creates a Native module

public class NativeModule extends JsModule {
    @Override
    public String getModuleName() {
        return "native";
    }
}

2.Create Native Method

Module inside the creation method requires the use of annotations @ JSBridgeMethod, by default Java method name is JS call method name, also specify the name of the calling method by @JSBridgeMethod (methodName = "xx")。Method can not be static or abstract, method can contain the return type, if the return type is the object, default return string to JS, the method parameters for the following types, you can directly map to their corresponding JS type

Java Types Mapping the JS type
Boolean / boolean Bool
Integer/ int Number
Float / float Number
Double / double Number
Long / long Number
String String
JBCallback function
JBMap Object
JBArray Array

for more convenient to call, we define the method parameters as ajax, we look at the ajax request structure

$.ajax({
    type:'GET',
    url:'xxx.com',
    dataType:'text'
    data:{a:1, b:'xx'},
    success:function(data){
    },
    error:function(err){
    }
})

Ajax method parameter is a JS object, the object contains type, url, dataType three string parameters, data parameter is an object, success and error is JS callback method, let's define the Java method.

@JSBridgeMethod
public void ajax(JBMap dataMap) {
        String type = dataMap.getString("type");
        String url = dataMap.getString("url");
        JBMap data = dataMap.getJBMap("data");
        JBCallback successCallback = dataMap.getCallback("success");
        JBCallback errorCallback = dataMap.getCallback("error");
        // Omit the request code
        if (request success) {
              successCallback.apply("success");
        } else {
              errorCallback.apply("failure");
        }
}

must add annotations @JSBridgeMethod,the parameter is JBMap

JBCallback.apply callback JS callback method,variable parameter,support for Java basic types,Array (WritableJBArray),and Object(WritableJBMap), if for other objects, the default converted to string

3.Register Module

There are two ways to register a Module, Default registration, Dynamic registration

JsBridgeConfig.getSetting().registerDefaultModule(NativeModule.class);

// or

JsBridge.loadModule(NativeModule.class)

JsBridgeConfig parameter:

Method Type Description Default
setProtocol string The name of the object that JS calls JsBridge
setLoadReadyMethod string Load the completion of the callback function onJsBridgeReady
registerDefaultModule JsModule Common module, default load None
debugMode bool In debug mode, the output TAG is the JsBridgeDebug log false

4.WebView inject method & listen callback

public class WebViewActivity extends BaseActivity {
   private JsBridge jsBridge;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
         ...
       jsBridge = JsBridge.loadModule();
       ...
       webView.setWebChromeClient(new WebChromeClient() {
           @Override
           public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
               // listen callback
               jsBridge.callJsPrompt(message, result);
               return true;
           }
       });

       webView.setWebViewClient(new WebViewClient() {
           @Override
           public void onPageFinished(WebView view, String url) {
               super.onPageFinished(view, url);
               // inject JS
               jsBridge.injectJs(view);
           }
       });
   }

   @Override
   protected void onDestroy() {
       // Avoid memory leaks
       jsBridge.release();
       super.onDestroy();
   }
}

Now, in JS code can call this method:

JsBridge.native.ajax({
    type:'GET',
    url:'xxx.com',
    dataType:'text'
    data:{a:1, b:'xx'},
    success:function(data){
    },
    error:function(err){
    }
})

If it is like calling JsBridge.ajax({...}), change the parent class from JsModule to JsStaticModule

There are some important information, because JS execution is asynchronous, in order to ensure that injection JS has been completed, please implement the method in the callback, or judge JsBridge object exists

window.onJsBridgeReady = function () {
    JsBridge.native.ajax({...});
}

// or
document.addEventListener('onJsBridgeReady', function(){
    JsBridge.native.ajax({...});
})

// or
if (JsBridge) {
    JsBridge.native.ajax({...});
}

For documentation and additional information see wiki and sample

Proguard

-keep class com.apkfuns.jsbridge.**{*;}
-keep class * extends com.apkfuns.jsbridge.module.JsModule{*;}

License

Copyright pengwei1024

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

jsbridge's People

Contributors

pengwei1024 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsbridge's Issues

求教,延迟几秒之后callback.apply(),H5页面无法收到回调

作者你好,我在项目中接入了jsbridge。目前有这样一个需求,在H5调用native的某一方法后,需要先通过网络请求拿到数据,然后将请求到的数据通过callback.apply()返回给H5页面。现在的情况是请求到数据之后callback.apply并没有触发H5页面的function回调,如果直接callback.apply()则可以正常回传数据。
js端代码:

bridge.call('native', 'getReadInfo', {}, function(result) {
  console.log(result)
}

java端代码:

@Override
    public void getReadInfo(String type, String code, String jsonString, JBCallback callback){
       //模拟网络请求
      new Handler().postDelayed(() -> {
              callback.apply("s"); //此处调用无效
     },3000);
    callback.apply("s");//调用有效
}

更新日志

麻烦请教一下,第一次引入这个库的时候,版本还是2.0.1,现在我看已经是2.2.1了,麻烦请教一下有什么更新么?

还有一个问题就是,如果在activity的onDestroy中没有调用jsBridge.release()的话,此时我重新打开一个新的界面,会导致JsBridge的调用还会响应的问题吧

README updates, English translation, differences with Ponto/Jockey

Hi Pengwei,

Is there a possibility of an English translation of the README and maybe the linked blogpost? Google translate doesn't do a very good job.

Also is JsBridge better or does it have different benefits than other projects that use the WebView javascript: method of bridging? Two projects I'm familiar with that do the same are: Ponto and JockeyJS. Neither has been updated in a while though.

One of the things I like about Jockey is it's service component. But I've also noticed that sending two payloads from the WebView back to the java receiver in quick succession results in the first payload being lost.

Thanks!

作者你好,请问JSBridgeMethod的函数有办法让其在webview的js异步线程中调用吗

目前JSBridgeMethod注解的回调函数,最开始是从onJsPrompt开始执行的(onJsPrompt是运行在ui线程的),所以也运行在ui线程中,我理解的。

以前写的一些原生js接口都是JavascriptInterface注解写的,中间有一些同步代码,如果ui线程中执行会阻塞,所以请问下作者有没有办法让JSBridgeMethod注解的回调函数跟JavascriptInterface一样都运行在webview的js线程中。

在魅族手机上有时候不管用,不知道跟框架有关吗

05-11 19:36:30.644 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.024 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.261 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.435 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.623 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.795 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:31.970 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:32.196 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:32.379 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:32.564 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:32.749 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:32.955 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:33.129 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()
05-11 19:36:33.334 10839-10839/com.android.like E/chromium: [ERROR:aw_autofill_client.cc(175)] Not implemented reached in virtual void android_webview::AwAutofillClient::OnFirstUserGestureObserved()

网页上点击一次 则实现JS调用JAVA一次,结果点一次 出一次这种提示,而且界面无反应,偶尔打开的时候可以点击,目前只在魅族上发现这个问题,我找到网络上有人有这个问题,但是他的实现方式和框架不同,所以不知道如何解决了
类同问题网址:https://blog.csdn.net/chen364567628/article/details/79309778

Call JsMethod <doAction> Error,希望大佬能帮忙排查一下原因

版本:2.1.1
情况:升级了一下友盟的SDK,然后js页面加载就报错了
image

报错:
Call JsMethod Error
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.apkfuns.jsbridge.f.a(JsMethod.java:130)
at com.apkfuns.jsbridge.e.a(JsBridgeImpl.java:302)
at com.apkfuns.jsbridge.e.callJsPrompt(JsBridgeImpl.java:151)
at NewWebChromeClient.onJsPrompt(NewWebChromeClient.java:41)
at W5.run(chromium-TrichromeWebViewGoogle.aab-stable-432415233:8)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:227)
at android.app.ActivityThread.main(ActivityThread.java:7804)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:984)
Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/umeng/social/tool/UMImageMark;
at java.lang.Class.getDeclaredFields(Native Method)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:152)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
image

传输图片时候报 json解析异常,有什么好的建议解决吗?

网页那边把图片base64处理后传给我,但是json报错,替换json解析工具可以解决吗?还是本身js交互传递的参数长度有限?
2019-07-25 11:20:29.116 E/JsBridgeDebug: JBArgumentParser::parse Exception
2019-07-25 11:20:29.117 E/JsBridgeDebug: org.json.JSONException: Unterminated string at character 10240 of {"id":957,"module":"@static","method":"saveImg","parameters":[{"type":1,"name":"957_a0","value":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKkAAACtCAYAAAG8Q2+vAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccl.....

其实这个框架比星星最多的那个更简单好用

两个都对比过了 星星多的那个是美国人开发的 传递中文的时候还需要调整 第二个框架的弱点是 Android如何主动发起调用 调用JS的方法 基本上所有的起点都必须凑JS层发出 然后安卓回调JS传值 这一点恰恰是第一个框架用起来方便 各有千秋吧

JsBridge库精简

提个建议,感觉项目里面用到json解析的地方不多,这里不需要引进fastJson,一些对包大小敏感的app,fastjson感觉还是挺大的

传递图片base64有问题

Refusing to load URL as it exceeds 2097152 characters,会报这个错,我是把图片转成base64字符,然后给h5。好像桥接有显示,字符串长度超过2M就不行了

Caused by: java.lang.NullPointerException

Caused by: java.lang.NullPointerException
at com.apkfuns.jsbridge.module.b.getBoolean(JBMapImpl.java:42)
at com.apkfuns.jsbridge.module.WritableJBMap$Create.getBoolean(WritableJBMap.java:28)
at com.master.kr.com.apkfuns.jsbridgesample.module.ServiceModule.ajax(ServiceModule.java:75)

dataMap.getBoolean(name) 实现方法有问题!

    dataMap.getBoolean("aa");  ----> NullPointerException
    dataMap.getDouble("bb");  ----> NullPointerException
    dataMap.getInt("int");  ----> NullPointerException
    dataMap.getLong("aaa");  ----> NullPointerException
    dataMap.getJBArray("bbb");---->ok
    getString(  )   ---->ok
    其他GET方法都正常  有空指针的都在上面

简单说 以上发生空指针的都是 没有set对应值时发生的
应该在GET时 赋予默认值 或NULL 并不应该发生异常!

关于onMyBridgeReady方法

麻烦请教一下,关于onMyBridgeReady是如何通知到前端JS已经注入完成的?这里还是有点模糊

JBArgument Parse error

一直报JBArgument Parse error

jsBridge.networkInfo({
success:function(e){
Dialog({
title: "成功",
content: e
});
},
fail:function(e){
Dialog({
title: "成功",
content: e
});
}
})
js端就这样调用,偶发性会报Parse error

前端的JsBridge这个类怎么调用呢?

JsBridge.ajax({
type:'GET',
url:'xxx.com',
dataType:'text'
data:{a:1, b:'xx'},
success:function(data){
},
error:function(err){
}
})
JsBridge这个类,前端同学不知道从哪里调用

FragmentTabHost 下失效问题

具体描述:
JS通过桥调用android HTTP方法得到返回后回调通知JS
在单一activity窗口 测试时没有问题的
现在多页面同时打开3个WEBVIEW 在HTTP得到返回调用JS这个环节则失败

我不是很理解,但觉得应该是多WEBVIEW 下 调用3份js 哪一份出现的问题,
望给出解决方案!

window.onJsBridgeReady 回调好多次怎么破?

console.log("window.onJsBridgeReady = function () {")
window.onJsBridgeReady = function () {
console.log("window.onJsBridgeReady")
JsBridge.mp.getCurrentUser({
success: data => {
console.log("JsBridge.mp.getCurrentUser")
console.log(data)
// resolve(JSON.parse(data))
},
error: (err) => {
console.log(err)
// reject(err)
}
})
// mp.getCurrentUser().then(res=>{
// console.log("返回的东西")
// console.log(res)
// })
}

sample ajax方法传输 复杂json数据 转化json失败

/sample/src/main/java/com/apkfuns/jsbridgesample/module/ServiceModule.java
ajax 方法
从服务器端返回的 复杂json字符串(含有html编辑器的数据),js接收后转化为json会失败。
将返回结果 改为 base64字符串 ,js再反向转 就正常了。

关于protocol设置的问题

对于JsBridgeConfig.getSetting().setProtocol(),这个方法,貌似只能设置一次protocol,而且再也无法更改了。感觉这样不太灵活,希望能够在release的时候清空protocol的信息,或者能够支持protocol的更改

请问JAVA层 如何直接调用JS的方法?

感谢您的分享,发现demo中都是js层首先发起调用,调用Android 安卓执行完任务再回调JS。那么应用场景如果是Android首先发起调用 可以做到吗?如何操作 就是JS中直接监听Android的调用,这点可以做到吗?谢谢...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.