├── .gitignore ├── JsBridge.gif ├── README.md ├── build.gradle ├── example ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── demo.html │ ├── java │ └── com │ │ └── github │ │ └── lzyzsd │ │ └── jsbridge │ │ └── example │ │ └── MainActivity.java │ └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ └── values │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── WebViewJavascriptBridge.js │ ├── java │ └── com │ │ └── github │ │ └── lzyzsd │ │ └── jsbridge │ │ ├── BridgeHandler.java │ │ ├── BridgeUtil.java │ │ ├── BridgeWebView.java │ │ ├── BridgeWebViewClient.java │ │ ├── CallBackFunction.java │ │ └── Message.java │ └── res │ └── values │ └── strings.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | 6 | # files for the dex VM 7 | *.dex 8 | 9 | 10 | # Java class files 11 | *.class 12 | 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | 23 | # Windows thumbnail db 24 | Thumbs.db 25 | 26 | 27 | # OSX files 28 | .DS_Store 29 | 30 | 31 | # Eclipse project files 32 | .classpath 33 | .project 34 | 35 | 36 | # Android Studio 37 | .idea 38 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 39 | .gradle 40 | build/ 41 | 42 | 43 | # Signing files 44 | .signing/ 45 | 46 | 47 | # User-specific configurations 48 | .idea/libraries/ 49 | .idea/workspace.xml 50 | .idea/tasks.xml 51 | .idea/.name 52 | .idea/compiler.xml 53 | .idea/copyright/profiles_settings.xml 54 | .idea/encodings.xml 55 | .idea/misc.xml 56 | .idea/modules.xml 57 | .idea/scopes/scope_settings.xml 58 | .idea/vcs.xml 59 | *.iml 60 | -------------------------------------------------------------------------------- /JsBridge.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/JsBridge.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 前言 2 | 3 | 本库是从"大头鬼"的JsBridge库fork后改造而来, 目的是与iOS/OSX平台, 大名鼎鼎的WebViewJavascriptBridge库保持一致的通信方案。 4 | 5 | 附: 6 | - "大头鬼"的JsBridge库地址: [JsBridge](https://github.com/lzyzsd/JsBridge) (微信也采用了类似解决方案) 7 | - WebViewJavascriptBridge库地址: [WebViewJavascriptBridge](https://github.com/marcuswestin/WebViewJavascriptBridge) (Facebook等大公司都在使用) 8 | 9 | ### 使用步骤 10 | 11 | 1) 使用com.github.lzyzsd.jsbridge.BridgeWebView替代WebView, 例如XML中: 12 | 13 | ``` 14 | 18 | ``` 19 | 20 | 2) 在Java中注册handler, 调用JS的handler 21 | 22 | ``` 23 | webView = (BridgeWebView) findViewById(R.id.webView); 24 | 25 | webView.registerHandler("testObjcCallback", new BridgeHandler() { 26 | @Override 27 | public void handler(String data, CallBackFunction function) { 28 | Log.i(TAG, "testObjcCallback called: " + data); 29 | function.onCallBack("Response from testObjcCallback"); 30 | } 31 | }); 32 | 33 | webView.callHandler("testJavascriptHandler", "{\"greetingFromObjC\": \"Hi there, JS!\"}", new CallBackFunction() { 34 | @Override 35 | public void onCallBack(String data) { 36 | Log.i(TAG, "testJavascriptHandler responded: " + data); 37 | } 38 | }); 39 | ``` 40 | 41 | 3) 拷贝 setupWebViewJavascriptBridge 这段方法到JS中: 42 | 43 | ``` 44 | function setupWebViewJavascriptBridge(callback) { 45 | if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } 46 | if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } 47 | window.WVJBCallbacks = [callback]; 48 | var WVJBIframe = document.createElement('iframe'); 49 | WVJBIframe.style.display = 'none'; 50 | WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; 51 | document.documentElement.appendChild(WVJBIframe); 52 | setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) 53 | } 54 | ``` 55 | 56 | 4) 最后, JS中执行 setupWebViewJavascriptBridge 方法, 并用bridge去注册handler和调用Java的handler 57 | 58 | ``` 59 | setupWebViewJavascriptBridge(function(bridge) { 60 | 61 | /* Initialize your app here */ 62 | 63 | bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) { 64 | console.log('ObjC called testJavascriptHandler with', data) 65 | var responseData = { 'Javascript Says':'Right back atcha!' } 66 | console.log('JS responding with', responseData) 67 | responseCallback(responseData) 68 | }) 69 | bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) { 70 | console.log('JS got response', response) 71 | }) 72 | }) 73 | ``` 74 | 75 | ### 关于JsBridge和WebViewJavascriptBridge的对比使用, 参考这篇博客: 76 | 77 | [聊一聊 webview 与 JS 交互方案 - 适用 Android & iOS](http://www.jianshu.com/p/c565c8f93abd) 78 | 79 | ## License 80 | 81 | This project is licensed under the terms of the MIT license. 82 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | maven { url "https://jitpack.io" } 18 | jcenter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "com.github.lzyzsd.jsbridge.example" 9 | minSdkVersion 9 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile project(':library') 25 | compile 'com.android.support:appcompat-v7:21.0.3' 26 | compile 'com.google.code.gson:gson:2.3.1' 27 | } 28 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/bruce/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /example/src/main/assets/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 |

WebViewJavascriptBridge Demo

12 | 59 |
60 | 61 | -------------------------------------------------------------------------------- /example/src/main/java/com/github/lzyzsd/jsbridge/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.jsbridge.example; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.View.OnClickListener; 8 | import android.webkit.WebChromeClient; 9 | 10 | import com.github.lzyzsd.jsbridge.BridgeHandler; 11 | import com.github.lzyzsd.jsbridge.BridgeWebView; 12 | import com.github.lzyzsd.jsbridge.CallBackFunction; 13 | 14 | public class MainActivity extends Activity { 15 | 16 | private final String TAG = "MainActivity"; 17 | 18 | BridgeWebView webView; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | 25 | webView = (BridgeWebView) findViewById(R.id.webView); 26 | 27 | webView.setWebChromeClient(new WebChromeClient()); 28 | 29 | webView.loadUrl("file:///android_asset/demo.html"); 30 | 31 | webView.registerHandler("testObjcCallback", new BridgeHandler() { 32 | 33 | @Override 34 | public void handler(String data, CallBackFunction function) { 35 | Log.i(TAG, "testObjcCallback called: " + data); 36 | function.onCallBack("Response from testObjcCallback"); 37 | } 38 | 39 | }); 40 | 41 | webView.callHandler("testJavascriptHandler", "{\"foo\":\"before ready\"}", new CallBackFunction() { 42 | @Override 43 | public void onCallBack(String data) { 44 | 45 | } 46 | }); 47 | 48 | findViewById(R.id.button).setOnClickListener(new OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | webView.callHandler("testJavascriptHandler", "{\"greetingFromObjC\": \"Hi there, JS!\"}", new CallBackFunction() { 52 | 53 | @Override 54 | public void onCallBack(String data) { 55 | // TODO Auto-generated method stub 56 | Log.i(TAG, "testJavascriptHandler responded: " + data); 57 | } 58 | 59 | }); 60 | } 61 | }); 62 | 63 | findViewById(R.id.reload).setOnClickListener(new OnClickListener() { 64 | @Override 65 | public void onClick(View v) { 66 | webView.loadUrl("file:///android_asset/demo.html"); 67 | } 68 | }); 69 | 70 | findViewById(R.id.disable).setOnClickListener(new OnClickListener() { 71 | @Override 72 | public void onClick(View v) { 73 | webView.callHandler("_disableJavascriptAlertBoxSafetyTimeout", null, null); 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 25 | 26 | 34 | 43 | 44 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/example/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/example/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/example/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/example/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JsBridge 3 | Java调用Web 4 | 5 | -------------------------------------------------------------------------------- /example/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyvenzhu/JsBridge/f18f03dd8b2e20b86364b04a26436ddbc35acffa/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version = "1.0.0" 4 | 5 | android { 6 | compileSdkVersion 21 7 | buildToolsVersion "21.1.2" 8 | 9 | defaultConfig { 10 | minSdkVersion 9 11 | targetSdkVersion 21 12 | versionCode 1 13 | versionName version 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | } 25 | 26 | def siteUrl = 'https://github.com/lzyzsd/JsBridge' 27 | def gitUrl = 'https://github.com/lzyzsd/JsBridge.git' 28 | group = "com.github.lzyzsd.jsbridge" 29 | task sourcesJar(type: Jar) { 30 | from android.sourceSets.main.java.srcDirs 31 | classifier = 'sources' 32 | } 33 | task javadoc(type: Javadoc) { 34 | source = android.sourceSets.main.java.srcDirs 35 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 36 | } 37 | task javadocJar(type: Jar, dependsOn: javadoc) { 38 | classifier = 'javadoc' 39 | from javadoc.destinationDir 40 | } 41 | artifacts { 42 | archives javadocJar 43 | archives sourcesJar 44 | } 45 | Properties properties = new Properties() 46 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) -------------------------------------------------------------------------------- /library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/bruce/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /library/src/main/assets/WebViewJavascriptBridge.js: -------------------------------------------------------------------------------- 1 | //notation: js file can only use this kind of comments 2 | //since comments will cause error when use in webview.loadurl, 3 | //comments will be remove by java use regexp 4 | (function() { 5 | if (window.WebViewJavascriptBridge) { 6 | return; 7 | } 8 | 9 | if (!window.onerror) { 10 | window.onerror = function(msg, url, line) { 11 | console.log("WebViewJavascriptBridge: ERROR:" + msg + "@" + url + ":" + line); 12 | } 13 | } 14 | window.WebViewJavascriptBridge = { 15 | registerHandler: registerHandler, 16 | callHandler: callHandler, 17 | disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout, 18 | _fetchQueue: _fetchQueue, 19 | _handleMessageFromObjC: _handleMessageFromObjC 20 | }; 21 | 22 | var messagingIframe; 23 | var sendMessageQueue = []; 24 | var messageHandlers = {}; 25 | 26 | var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'; 27 | var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__'; 28 | 29 | var responseCallbacks = {}; 30 | var uniqueId = 1; 31 | var dispatchMessagesWithTimeoutSafety = true; 32 | 33 | function registerHandler(handlerName, handler) { 34 | messageHandlers[handlerName] = handler; 35 | } 36 | 37 | function callHandler(handlerName, data, responseCallback) { 38 | if (arguments.length == 2 && typeof data == 'function') { 39 | responseCallback = data; 40 | data = null; 41 | } 42 | _doSend({ handlerName:handlerName, data:data }, responseCallback); 43 | } 44 | function disableJavscriptAlertBoxSafetyTimeout() { 45 | dispatchMessagesWithTimeoutSafety = false; 46 | } 47 | 48 | function _doSend(message, responseCallback) { 49 | if (responseCallback) { 50 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); 51 | responseCallbacks[callbackId] = responseCallback; 52 | message['callbackId'] = callbackId; 53 | } 54 | sendMessageQueue.push(message); 55 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; 56 | } 57 | 58 | function _fetchQueue() { 59 | var messageQueueString = JSON.stringify(sendMessageQueue); 60 | sendMessageQueue = []; 61 | // return messageQueueString; // Android无法直接返回数据, 这是与iOS最大的区别; 所以, 需要使用自定义url形式返回数据。 62 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString); 63 | } 64 | 65 | function _dispatchMessageFromObjC(messageJSON) { 66 | if (dispatchMessagesWithTimeoutSafety) { 67 | setTimeout(_doDispatchMessageFromObjC); 68 | } else { 69 | _doDispatchMessageFromObjC(); 70 | } 71 | 72 | function _doDispatchMessageFromObjC() { 73 | var message = JSON.parse(messageJSON); 74 | var messageHandler; 75 | var responseCallback; 76 | if (message.responseId) { 77 | responseCallback = responseCallbacks[message.responseId]; 78 | if (!responseCallback) { 79 | return; 80 | } 81 | responseCallback(message.responseData); 82 | delete responseCallbacks[message.responseId]; 83 | } else { 84 | if (message.callbackId) { 85 | var callbackResponseId = message.callbackId; 86 | responseCallback = function(responseData) { 87 | _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); 88 | }; 89 | } 90 | 91 | var handler = messageHandlers[message.handlerName]; 92 | if (!handler) { 93 | console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); 94 | } else { 95 | handler(message.data, responseCallback); 96 | } 97 | } 98 | } 99 | } 100 | 101 | function _handleMessageFromObjC(messageJSON) { 102 | _dispatchMessageFromObjC(messageJSON); 103 | } 104 | 105 | messagingIframe = document.createElement('iframe'); 106 | messagingIframe.style.display = 'none'; 107 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; 108 | document.documentElement.appendChild(messagingIframe); 109 | 110 | registerHandler("_disableJavascriptAlertBoxSafetyTimeout", disableJavscriptAlertBoxSafetyTimeout); 111 | 112 | setTimeout(_callWVJBCallbacks, 0); 113 | function _callWVJBCallbacks() { 114 | var callbacks = window.WVJBCallbacks; 115 | delete window.WVJBCallbacks; 116 | for (var i=0; i= 2) { 38 | StringBuilder sb = new StringBuilder(); 39 | for (int i = 1; i < functionAndData.length; i++) { 40 | sb.append(functionAndData[i]); 41 | } 42 | return sb.toString(); 43 | } 44 | return null; 45 | } 46 | 47 | public static String getFunctionFromReturnUrl(String url) { 48 | String temp = url.replace(WVJB_RETURN_DATA, EMPTY_STR); 49 | String[] functionAndData = temp.split(SPLIT_MARK); 50 | if(functionAndData.length >= 1){ 51 | return functionAndData[0]; 52 | } 53 | return null; 54 | } 55 | 56 | public static void webViewLoadLocalJs(WebView view, String path){ 57 | String jsContent = assetFile2Str(view.getContext(), path); 58 | view.loadUrl("javascript:" + jsContent); 59 | } 60 | 61 | public static String assetFile2Str(Context c, String urlStr){ 62 | InputStream in = null; 63 | try{ 64 | in = c.getAssets().open(urlStr); 65 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in)); 66 | String line = null; 67 | StringBuilder sb = new StringBuilder(); 68 | do { 69 | line = bufferedReader.readLine(); 70 | if (line != null && !line.matches("^\\s*\\/\\/.*")) { 71 | sb.append(line); 72 | } 73 | } while (line != null); 74 | 75 | bufferedReader.close(); 76 | in.close(); 77 | 78 | return sb.toString(); 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | } finally { 82 | if(in != null) { 83 | try { 84 | in.close(); 85 | } catch (IOException e) { 86 | } 87 | } 88 | } 89 | return null; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /library/src/main/java/com/github/lzyzsd/jsbridge/BridgeWebView.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.jsbridge; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.os.Looper; 7 | import android.os.SystemClock; 8 | import android.text.TextUtils; 9 | import android.util.AttributeSet; 10 | import android.webkit.WebView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | @SuppressLint("SetJavaScriptEnabled") 18 | public class BridgeWebView extends WebView { 19 | 20 | private final String TAG = "BridgeWebView"; 21 | 22 | public static final String toLoadJs = "WebViewJavascriptBridge.js"; 23 | Map responseCallbacks = new HashMap(); 24 | Map messageHandlers = new HashMap(); 25 | 26 | private List startupMessage = new ArrayList(); 27 | 28 | public List getStartupMessage() { 29 | return startupMessage; 30 | } 31 | 32 | public void setStartupMessage(List startupMessage) { 33 | this.startupMessage = startupMessage; 34 | } 35 | 36 | private long uniqueId = 0; 37 | 38 | public BridgeWebView(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | init(); 41 | } 42 | 43 | public BridgeWebView(Context context, AttributeSet attrs, int defStyle) { 44 | super(context, attrs, defStyle); 45 | init(); 46 | } 47 | 48 | public BridgeWebView(Context context) { 49 | super(context); 50 | init(); 51 | } 52 | 53 | private void init() { 54 | this.setVerticalScrollBarEnabled(false); 55 | this.setHorizontalScrollBarEnabled(false); 56 | this.getSettings().setJavaScriptEnabled(true); 57 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 58 | WebView.setWebContentsDebuggingEnabled(true); 59 | } 60 | this.setWebViewClient(generateBridgeWebViewClient()); 61 | } 62 | 63 | protected BridgeWebViewClient generateBridgeWebViewClient() { 64 | return new BridgeWebViewClient(this); 65 | } 66 | 67 | void handlerReturnData(String url) { 68 | String functionName = BridgeUtil.getFunctionFromReturnUrl(url); 69 | CallBackFunction f = responseCallbacks.get(functionName); 70 | String data = BridgeUtil.getDataFromReturnUrl(url); 71 | if (f != null) { 72 | f.onCallBack(data); 73 | responseCallbacks.remove(functionName); 74 | return; 75 | } 76 | } 77 | 78 | private void doSend(String handlerName, String data, CallBackFunction responseCallback) { 79 | Message m = new Message(); 80 | if (!TextUtils.isEmpty(data)) { 81 | m.setData(data); 82 | } 83 | if (responseCallback != null) { 84 | String callbackStr = String.format(BridgeUtil.CALLBACK_ID_FORMAT, ++uniqueId + (BridgeUtil.UNDERLINE_STR + SystemClock.currentThreadTimeMillis())); 85 | responseCallbacks.put(callbackStr, responseCallback); 86 | m.setCallbackId(callbackStr); 87 | } 88 | if (!TextUtils.isEmpty(handlerName)) { 89 | m.setHandlerName(handlerName); 90 | } 91 | queueMessage(m); 92 | } 93 | 94 | private void queueMessage(Message m) { 95 | if (startupMessage != null) { 96 | startupMessage.add(m); 97 | } else { 98 | dispatchMessage(m); 99 | } 100 | } 101 | 102 | void dispatchMessage(Message m) { 103 | String messageJson = m.toJson(); 104 | //escape special characters for json string 105 | messageJson = messageJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2"); 106 | messageJson = messageJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\""); 107 | String javascriptCommand = String.format(BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson); 108 | if (Thread.currentThread() == Looper.getMainLooper().getThread()) { 109 | this.loadUrl(javascriptCommand); 110 | } 111 | } 112 | 113 | void flushMessageQueue() { 114 | if (Thread.currentThread() == Looper.getMainLooper().getThread()) { 115 | loadUrl(BridgeUtil.JS_FETCH_QUEUE_FROM_JAVA, new CallBackFunction() { 116 | 117 | @Override 118 | public void onCallBack(String data) { 119 | // deserializeMessage 120 | List list = null; 121 | try { 122 | list = Message.toArrayList(data); 123 | } catch (Exception e) { 124 | e.printStackTrace(); 125 | return; 126 | } 127 | if (list == null || list.size() == 0) { 128 | return; 129 | } 130 | for (int i = 0; i < list.size(); i++) { 131 | Message m = list.get(i); 132 | String responseId = m.getResponseId(); 133 | // 是否是response 134 | if (!TextUtils.isEmpty(responseId)) { 135 | CallBackFunction function = responseCallbacks.get(responseId); 136 | String responseData = m.getResponseData(); 137 | function.onCallBack(responseData); 138 | responseCallbacks.remove(responseId); 139 | } else { 140 | CallBackFunction responseFunction = null; 141 | // if had callbackId 142 | final String callbackId = m.getCallbackId(); 143 | if (!TextUtils.isEmpty(callbackId)) { 144 | responseFunction = new CallBackFunction() { 145 | @Override 146 | public void onCallBack(String data) { 147 | Message responseMsg = new Message(); 148 | responseMsg.setResponseId(callbackId); 149 | responseMsg.setResponseData(data); 150 | queueMessage(responseMsg); 151 | } 152 | }; 153 | } else { 154 | responseFunction = new CallBackFunction() { 155 | @Override 156 | public void onCallBack(String data) { 157 | // do nothing 158 | } 159 | }; 160 | } 161 | BridgeHandler handler = null; 162 | if (!TextUtils.isEmpty(m.getHandlerName())) { 163 | handler = messageHandlers.get(m.getHandlerName()); 164 | } else { 165 | // no handler found 166 | } 167 | if (handler != null){ 168 | handler.handler(m.getData(), responseFunction); 169 | } 170 | } 171 | } 172 | } 173 | }); 174 | } 175 | } 176 | 177 | public void loadUrl(String jsUrl, CallBackFunction returnCallback) { 178 | this.loadUrl(jsUrl); 179 | responseCallbacks.put(BridgeUtil.parseFunctionName(jsUrl), returnCallback); 180 | } 181 | 182 | /** 183 | * register handler,so that javascript can call it 184 | * 185 | * @param handlerName 186 | * @param handler 187 | */ 188 | public void registerHandler(String handlerName, BridgeHandler handler) { 189 | if (handler != null) { 190 | messageHandlers.put(handlerName, handler); 191 | } 192 | } 193 | 194 | /** 195 | * call javascript registered handler 196 | * 197 | * @param handlerName 198 | * @param data 199 | * @param callBack 200 | */ 201 | public void callHandler(String handlerName, String data, CallBackFunction callBack) { 202 | doSend(handlerName, data, callBack); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /library/src/main/java/com/github/lzyzsd/jsbridge/BridgeWebViewClient.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.jsbridge; 2 | 3 | import android.graphics.Bitmap; 4 | import android.webkit.WebView; 5 | import android.webkit.WebViewClient; 6 | 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.URLDecoder; 9 | 10 | /** 11 | * Created by bruce on 10/28/15. 12 | */ 13 | public class BridgeWebViewClient extends WebViewClient { 14 | private BridgeWebView webView; 15 | 16 | public BridgeWebViewClient(BridgeWebView webView) { 17 | this.webView = webView; 18 | } 19 | 20 | @Override 21 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 22 | try { 23 | url = URLDecoder.decode(url, "UTF-8"); 24 | } catch (UnsupportedEncodingException e) { 25 | e.printStackTrace(); 26 | } 27 | 28 | if (url.startsWith(BridgeUtil.WVJB_BRIDGE_LOADED)) { 29 | BridgeUtil.webViewLoadLocalJs(view, BridgeWebView.toLoadJs); 30 | 31 | if (webView.getStartupMessage() != null) { 32 | for (Message m : webView.getStartupMessage()) { 33 | webView.dispatchMessage(m); 34 | } 35 | webView.setStartupMessage(null); 36 | } 37 | return true; 38 | } else if (url.startsWith(BridgeUtil.WVJB_RETURN_DATA)) { // 如果是返回数据 39 | webView.handlerReturnData(url); 40 | return true; 41 | } else if (url.startsWith(BridgeUtil.WVJB_QUEUE_HAS_MESSAGE)) { // 消息队列有数据 42 | webView.flushMessageQueue(); 43 | return true; 44 | } else { 45 | return super.shouldOverrideUrlLoading(view, url); 46 | } 47 | } 48 | 49 | @Override 50 | public void onPageStarted(WebView view, String url, Bitmap favicon) { 51 | super.onPageStarted(view, url, favicon); 52 | } 53 | 54 | @Override 55 | public void onPageFinished(WebView view, String url) { 56 | super.onPageFinished(view, url); 57 | } 58 | 59 | @Override 60 | public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { 61 | super.onReceivedError(view, errorCode, description, failingUrl); 62 | } 63 | } -------------------------------------------------------------------------------- /library/src/main/java/com/github/lzyzsd/jsbridge/CallBackFunction.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.jsbridge; 2 | 3 | public interface CallBackFunction { 4 | 5 | public void onCallBack(String data); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /library/src/main/java/com/github/lzyzsd/jsbridge/Message.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.jsbridge; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * data of bridge 12 | * @author haoqing 13 | * 14 | */ 15 | public class Message { 16 | 17 | private String callbackId; //callbackId 18 | private String responseId; //responseId 19 | private String responseData; //responseData 20 | private String data; //data of message 21 | private String handlerName; //name of handler 22 | 23 | private final static String CALLBACK_ID_STR = "callbackId"; 24 | private final static String RESPONSE_ID_STR = "responseId"; 25 | private final static String RESPONSE_DATA_STR = "responseData"; 26 | private final static String DATA_STR = "data"; 27 | private final static String HANDLER_NAME_STR = "handlerName"; 28 | 29 | public String getResponseId() { 30 | return responseId; 31 | } 32 | public void setResponseId(String responseId) { 33 | this.responseId = responseId; 34 | } 35 | public String getResponseData() { 36 | return responseData; 37 | } 38 | public void setResponseData(String responseData) { 39 | this.responseData = responseData; 40 | } 41 | public String getCallbackId() { 42 | return callbackId; 43 | } 44 | public void setCallbackId(String callbackId) { 45 | this.callbackId = callbackId; 46 | } 47 | public String getData() { 48 | return data; 49 | } 50 | public void setData(String data) { 51 | this.data = data; 52 | } 53 | public String getHandlerName() { 54 | return handlerName; 55 | } 56 | public void setHandlerName(String handlerName) { 57 | this.handlerName = handlerName; 58 | } 59 | 60 | public String toJson() { 61 | JSONObject jsonObject= new JSONObject(); 62 | try { 63 | jsonObject.put(CALLBACK_ID_STR, getCallbackId()); 64 | jsonObject.put(DATA_STR, getData()); 65 | jsonObject.put(HANDLER_NAME_STR, getHandlerName()); 66 | jsonObject.put(RESPONSE_DATA_STR, getResponseData()); 67 | jsonObject.put(RESPONSE_ID_STR, getResponseId()); 68 | return jsonObject.toString(); 69 | } catch (JSONException e) { 70 | e.printStackTrace(); 71 | } 72 | return null; 73 | } 74 | 75 | public static Message toObject(String jsonStr) { 76 | Message m = new Message(); 77 | try { 78 | JSONObject jsonObject = new JSONObject(jsonStr); 79 | m.setHandlerName(jsonObject.has(HANDLER_NAME_STR) ? jsonObject.getString(HANDLER_NAME_STR):null); 80 | m.setCallbackId(jsonObject.has(CALLBACK_ID_STR) ? jsonObject.getString(CALLBACK_ID_STR):null); 81 | m.setResponseData(jsonObject.has(RESPONSE_DATA_STR) ? jsonObject.getString(RESPONSE_DATA_STR):null); 82 | m.setResponseId(jsonObject.has(RESPONSE_ID_STR) ? jsonObject.getString(RESPONSE_ID_STR):null); 83 | m.setData(jsonObject.has(DATA_STR) ? jsonObject.getString(DATA_STR):null); 84 | return m; 85 | } catch (JSONException e) { 86 | e.printStackTrace(); 87 | } 88 | return m; 89 | } 90 | 91 | public static List toArrayList(String jsonStr){ 92 | List list = new ArrayList(); 93 | try { 94 | JSONArray jsonArray = new JSONArray(jsonStr); 95 | for(int i = 0; i < jsonArray.length(); i++){ 96 | Message m = new Message(); 97 | JSONObject jsonObject = jsonArray.getJSONObject(i); 98 | m.setHandlerName(jsonObject.has(HANDLER_NAME_STR) ? jsonObject.getString(HANDLER_NAME_STR):null); 99 | m.setCallbackId(jsonObject.has(CALLBACK_ID_STR) ? jsonObject.getString(CALLBACK_ID_STR):null); 100 | m.setResponseData(jsonObject.has(RESPONSE_DATA_STR) ? jsonObject.getString(RESPONSE_DATA_STR):null); 101 | m.setResponseId(jsonObject.has(RESPONSE_ID_STR) ? jsonObject.getString(RESPONSE_ID_STR):null); 102 | m.setData(jsonObject.has(DATA_STR) ? jsonObject.getString(DATA_STR):null); 103 | list.add(m); 104 | } 105 | } catch (JSONException e) { 106 | e.printStackTrace(); 107 | } 108 | return list; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | library 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':example', ':library' 2 | --------------------------------------------------------------------------------