diff --git a/.gitignore b/.gitignore index e0f5342..4a07bae 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,9 @@ Pods */*/gen/ */*/build/ +# Web .idea +# Development +node_modules +bower_components diff --git a/Hybridge.podspec b/Hybridge.podspec index e76aaf5..990a4a7 100644 --- a/Hybridge.podspec +++ b/Hybridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Hybridge" - s.version = "1.1.0" + s.version = "1.2.0" s.summary = "Yet another javascript / mobile native simple bridge for hybrid apps, back and forth..." s.description = <<-DESC @@ -12,11 +12,11 @@ Pod::Spec.new do |s| s.license = { :type => "Affero GNU GPL v3", :file => "LICENSE.txt" } - s.authors = { 'David Garcia' => 'dgs30@tid.es', 'Guillermo Gonzalez' => 'gonzalezreal@icloud.com' } + s.authors = { 'David Garcia' => 'davidgarsan@gmail.com', 'Guillermo Gonzalez' => 'gonzalezreal@icloud.com' } s.platform = :ios s.ios.deployment_target = "6.0" - s.source = { :git => "https://github.com/gonzalezreal/tdigital-hybridge.git", :branch => "refactoring-ios" } + s.source = { :git => "https://github.com/telefonicaid/tdigital-hybridge.git", :tag => "1.2.0" } s.source_files = "ios/Hybridge/Hybridge/*.{h,m}" s.private_header_files = "ios/Hybridge/Hybridge/HYBURLProtocol.h", "ios/Hybridge/Hybridge/NSString+Hybridge.h" diff --git a/README.md b/README.md index 6afb27b..7ad4cad 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,10 @@ Yet another javascript / mobile native simple bridge for hybrid apps, back and f ## Index 1. [Why?](#why) - 1. [Getting Started](#start) - * [Dependencies](#dependencies) - * [Javascript](#dependencies_javascript) + 1. [Installation](#installation) + * [Javascript](#installation_javascript) + * [Android](#installation_android) + * [iOS](#installation_ios) 1. [Usage](#usage) * [Javascript](#usage_javascript) * [Android](#usage_android) @@ -31,14 +32,41 @@ Hybridge tries to make easy communication and data exchanging between native (iO **[[⬆]](#index)** -## Getting Started -Firstly, get the code by downloading the zip or cloning the project into your local. +## Installation +Hybridge follows [semantic versioning](http://semver.org/). In the `boilerplate` directory you can find examples of how to get running in the different platforms. -### Dependencies -#### Javascript -Hybridge works in an AMD fashion, so you'll need [RequireJS](http://requirejs.org) for the loading. +### Javascript + +Since v1.2.0, `hybridge` is available in [bower](http://bower.io/). Bower will install `hybridge` itself and all its dependencies. +```sh +bower install --save hybridge +``` + +Add it to your HTML +```html + +``` + +You can manually download the javascript [js/hybridge.js](js/hybridge.js) and use the traditional way. + +Hybridge works in both an AMD/Vanilla javascript fashion. For vanilla javascript, it's available in `window.Hybridge` variable. You'll also need [JQuery](http://jquery.com) (version 1.8.3 or newer) for the Javascript part since [Deferred](http://api.jquery.com/category/deferred-object) object is used intensively. + +### Android + +You can build your own Hybridge, but you can start with the latest version included at [hybridge.jar](boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.2.0.jar) in the boilerplate code. + +### iOS + +Add the following to your `Podfile` and run `$ pod install`. + +``` ruby +pod 'Hybridge' +``` + +If you don't have CocoaPods installed or integrated into your project, you can learn how to do so [here](http://cocoapods.org). + **[[⬆]](#index)** ## Usage @@ -57,13 +85,12 @@ Load `hybridge.js` as a module in your AMD code. Simplest setup: require.config({ baseUrl: 'js/lib', paths: { - jquery: 'jquery', - hybridge: 'hybridge' + jquery: 'bower_components/jquery/dist/jquery', + hybridge: 'bower_components/hybridge/js/hybridge' } }); - requirejs(['hybridge'], - function (Hybridge) { + require(['hybridge'], function (Hybridge) { Hybridge.init({ 'environment' : 'ios' } @@ -116,6 +143,7 @@ public class DownloadTask extends AsyncTask { private JsPromptResult result; private Context context; + private HybridgeBroadcaster hybridge; public DownloadTask(Context context) { this.context = context; @@ -125,6 +153,7 @@ public class DownloadTask extends AsyncTask { protected JSONObject doInBackground(Object... params) { JSONObject json = (JSONObject) params[0]; result = (JsPromptResult) params[1]; + hybridge = (HybridgeBroadcaster) params[2]; // Process download ... return json; @@ -161,14 +190,6 @@ public void update(Observable observable, Object data) { **[[⬆]](#index)** ### iOS -#### Installation -Add the following to your `Podfile` and run `$ pod install`. - -``` ruby -pod 'Hybridge' -``` - -If you don't have CocoaPods installed or integrated into your project, you can learn how to do so [here](http://cocoapods.org). #### Creating a Web View Controller Hybridge provides `HYBWebViewController`, a convenience view controller that hosts both a web view and a bridge object to communicate with it. Users are encouraged to subclass `HYBWebViewController` and specify any supported bridge actions. @@ -198,7 +219,7 @@ There are two different ways to handle bridge actions: } else if ([action isEqualToString:@"some_other_action"]) { // Handle 'some_other_action' } - + // Return a JSON dictionary or `nil` return nil; } @@ -248,7 +269,7 @@ HybridgeBroadcaster.getInstance(mWebView).fireJavascriptEvent(webView, Event.REA ``` ### iOS -Hybridge provides an `UIWebView` category that sports a convenience method to trigger events on the Javascript side. +Hybridge provides an `UIWebView` category that sports a convenience method to trigger events on the Javascript side. ```objc [self.webView hyb_fireEvent:HYBEventMessage data:@{ @"foo": @"bar" }]; diff --git a/android/Hybridge/AndroidManifest.xml b/android/Hybridge/AndroidManifest.xml index 33dc466..7bd9bb6 100644 --- a/android/Hybridge/AndroidManifest.xml +++ b/android/Hybridge/AndroidManifest.xml @@ -1,9 +1,9 @@ + android:versionCode="120" + android:versionName="1.2.0" > - \ No newline at end of file + diff --git a/android/Hybridge/src/com/pdi/hybridge/HybridgeBroadcaster.java b/android/Hybridge/src/com/pdi/hybridge/HybridgeBroadcaster.java index 38f1339..34bf6cc 100644 --- a/android/Hybridge/src/com/pdi/hybridge/HybridgeBroadcaster.java +++ b/android/Hybridge/src/com/pdi/hybridge/HybridgeBroadcaster.java @@ -35,8 +35,8 @@ private HybridgeBroadcaster() { public void initJs(WebView view, JSONArray actions, JSONArray events) { runJsInWebView(view, "window.HybridgeGlobal || setTimeout(function () {" + "window.HybridgeGlobal = {" + " isReady : true" + ", version : " - + HybridgeConst.VERSION + ", actions : " + actions.toString() + ", events : " - + events.toString() + "};" + + HybridgeConst.VERSION + ", versionMinor : " + HybridgeConst.VERSION_MINOR + + ", actions : " + actions.toString() + ", events : " + events.toString() + "};" + "(window.document.getElementById('hybridgeTrigger') || {}).className = 'switch';" + "},0)"); mIsInitialized = true; diff --git a/android/Hybridge/src/com/pdi/hybridge/HybridgeConst.java b/android/Hybridge/src/com/pdi/hybridge/HybridgeConst.java index d6ba668..7f19a51 100644 --- a/android/Hybridge/src/com/pdi/hybridge/HybridgeConst.java +++ b/android/Hybridge/src/com/pdi/hybridge/HybridgeConst.java @@ -9,14 +9,12 @@ public class HybridgeConst { public static final int VERSION = 1; + public static final int VERSION_MINOR = 2; public static final String EVENT_NAME = "event"; public enum Event { - PAUSE("pause"), - RESUME("resume"), - MESSAGE("message"), - READY("ready"); + PAUSE("pause"), RESUME("resume"), MESSAGE("message"), READY("ready"); private String jsName; diff --git a/android/Hybridge/version.properties b/android/Hybridge/version.properties index d5c3943..83cd022 100644 --- a/android/Hybridge/version.properties +++ b/android/Hybridge/version.properties @@ -2,5 +2,5 @@ #Version = ${build.platform.number}.${build.major.number}.${build.minor.number} build.revision.number=1 -build.major.number=0 +build.major.number=2 build.minor.number=0 diff --git a/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.0.0.jar b/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.0.0.jar deleted file mode 100644 index 260877d..0000000 Binary files a/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.0.0.jar and /dev/null differ diff --git a/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.2.0.jar b/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.2.0.jar new file mode 100644 index 0000000..b4e5e77 Binary files /dev/null and b/boilerplate/android/HybridgeBoilerplate/libs/hybridge-1.2.0.jar differ diff --git a/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/MainActivity.java b/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/MainActivity.java index 0077840..0b88d5d 100644 --- a/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/MainActivity.java +++ b/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/MainActivity.java @@ -6,12 +6,6 @@ package com.pdi.hybridge.boilerplate; -import java.util.Observable; -import java.util.Observer; - -import org.json.JSONException; -import org.json.JSONObject; - import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; @@ -21,47 +15,74 @@ import com.pdi.hybridge.HybridgeBroadcaster; import com.pdi.hybridge.HybridgeConst; +import com.pdi.hybridge.HybridgeConst.Event; import com.pdi.hybridge.HybridgeWebChromeClient; import com.pdi.hybridge.HybridgeWebViewClient; -import com.pdi.hybridge.HybridgeConst.Event; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Observable; +import java.util.Observer; public class MainActivity extends Activity implements Observer { - + private String mTag = "MainActivity"; private WebView mWebView; - + private HybridgeBroadcaster mHybridge; + // String keys for JSON data user in Hybridge communication public static final String JSON_KEY_INIT = "initialized"; - + @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - HybridgeBroadcaster.getInstance().addObserver(this); mWebView = (WebView) findViewById(R.id.webview); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(webViewClient); mWebView.setWebChromeClient(webChromeClient); + mHybridge = HybridgeBroadcaster.getInstance(mWebView); // Set the URL of your web app - mWebView.loadUrl("http://localhost/hybridge.html"); + mWebView.loadUrl("http://192.168.1.40/hybridge.html"); } - private final HybridgeWebViewClient webViewClient = new HybridgeWebViewClient(JsActionImpl.values()); + private final HybridgeWebViewClient webViewClient = new HybridgeWebViewClient( + JsActionImpl.values()); + + private final WebChromeClient webChromeClient = new HybridgeWebChromeClient( + JsActionImpl.values()); - private final WebChromeClient webChromeClient = new HybridgeWebChromeClient(JsActionImpl.values()); - @Override public void update(Observable observable, Object data) { - JSONObject json = (JSONObject) data; + final JSONObject json = (JSONObject) data; if (json.has(HybridgeConst.EVENT_NAME)) { try { - HybridgeBroadcaster.getInstance().fireJavascriptEvent(mWebView, (Event) json.get(HybridgeConst.EVENT_NAME), json); - } catch (JSONException e) { + mHybridge.fireJavascriptEvent(mWebView, (Event) json.get(HybridgeConst.EVENT_NAME), + json); + } catch (final JSONException e) { Log.e(mTag, "Problem with JSON object " + e.getMessage()); } } else { - HybridgeBroadcaster.getInstance().fireMessage(mWebView, json); + mHybridge.fireMessage(mWebView, json); } } + + /** + * Callback invoke once the fragment is created. + * + * @see android.app.Fragment#onResume() + */ + @Override + public void onResume() { + mHybridge.addObserver(this); + super.onResume(); + } + + @Override + public void onPause() { + mHybridge.deleteObserver(this); + super.onPause(); + } } diff --git a/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/action/InitTask.java b/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/action/InitTask.java index fb6cd85..a945a88 100644 --- a/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/action/InitTask.java +++ b/boilerplate/android/HybridgeBoilerplate/src/com/pdi/hybridge/boilerplate/action/InitTask.java @@ -6,9 +6,6 @@ package com.pdi.hybridge.boilerplate.action; -import org.json.JSONException; -import org.json.JSONObject; - import android.app.Activity; import android.content.Context; import android.os.AsyncTask; @@ -19,27 +16,32 @@ import com.pdi.hybridge.HybridgeConst; import com.pdi.hybridge.boilerplate.MainActivity; +import org.json.JSONException; +import org.json.JSONObject; + public class InitTask extends AsyncTask { private final String mTag = "InitTask"; - private JsPromptResult result; - private Context context; + private JsPromptResult mResult; + private Context mContext; + private HybridgeBroadcaster mHybridge; public InitTask(Activity activity) { - this.context = activity.getApplicationContext(); + mContext = activity.getApplicationContext(); } @Override protected JSONObject doInBackground(Object... params) { - JSONObject json = (JSONObject) params[0]; - result = (JsPromptResult) params[1]; + final JSONObject json = (JSONObject) params[0]; + mResult = (JsPromptResult) params[1]; + mHybridge = (HybridgeBroadcaster) params[2]; try { if (json.has(MainActivity.JSON_KEY_INIT)) { json.put(HybridgeConst.EVENT_NAME, HybridgeConst.Event.READY); - HybridgeBroadcaster.getInstance().updateState(json); + mHybridge.updateState(json); } - } catch (JSONException e) { + } catch (final JSONException e) { Log.e(mTag, "Download: Problem with JSON object " + e.getMessage()); } @@ -53,7 +55,7 @@ protected void onPreExecute() { @Override protected void onPostExecute(JSONObject json) { - result.confirm(json.toString()); + mResult.confirm(json.toString()); } -} \ No newline at end of file +} diff --git a/boilerplate/ios/HybridgeSample/Podfile b/boilerplate/ios/HybridgeSample/Podfile index e6cea73..54f2127 100644 --- a/boilerplate/ios/HybridgeSample/Podfile +++ b/boilerplate/ios/HybridgeSample/Podfile @@ -2,7 +2,7 @@ # platform :ios, "6.0" target "HybridgeSample" do - pod 'Hybridge', :path => '../../../' + pod 'Hybridge', :path => '../../..' end target "HybridgeSampleTests" do diff --git a/boilerplate/ios/HybridgeSample/Podfile.lock b/boilerplate/ios/HybridgeSample/Podfile.lock index 0c099ae..b7fad22 100644 --- a/boilerplate/ios/HybridgeSample/Podfile.lock +++ b/boilerplate/ios/HybridgeSample/Podfile.lock @@ -1,14 +1,14 @@ PODS: - - Hybridge (1.1.0) + - Hybridge (1.2.0) DEPENDENCIES: - - Hybridge (from `../../../`) + - Hybridge (from `../../..`) EXTERNAL SOURCES: Hybridge: - :path: ../../../ + :path: ../../.. SPEC CHECKSUMS: - Hybridge: 5ace862416316c8eaee9df4c1c5b8c6f21b938e8 + Hybridge: 9c0600c2faf4ba43b2c66b9fbbc714ce7cbfdc8d COCOAPODS: 0.33.1 diff --git a/boilerplate/www/hybridge.html b/boilerplate/www/hybridge.html index 510b0a1..bf0102a 100644 --- a/boilerplate/www/hybridge.html +++ b/boilerplate/www/hybridge.html @@ -72,7 +72,7 @@ // 'ready' callback, entry point for HyBridge action-event communication var processInit = function (event) { - statusWrapper.text('Hybridge (version ' + HybridgeGlobal.version + ') is ON'); + statusWrapper.text('Hybridge (version ' + HybridgeGlobal.version + '.' + HybridgeGlobal.versionMinor + ') is ON'); Hybridge.removeListener(Hybridge.events.ready, processInit); // Create a listbox with the implemented events @@ -109,7 +109,7 @@ Hybridge.addListener(Hybridge.events.ready, processInit); Hybridge.init({ - 'environment' : 'ios', + 'environment' : 'android', 'logger': logger }); } diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..93964bc --- /dev/null +++ b/bower.json @@ -0,0 +1,26 @@ +{ + "name": "hybridge", + "version": "1.2.0", + "homepage": "https://github.com/telefonicaid/tdigital-hybridge", + "description": "javascript / mobile native simple bridge for hybrid apps, back and forth...", + "main": "js/hybridge.js", + "keywords": [ + "native", + "javascript", + "ios", + "android", + "bridge", + "hybrid" + ], + "license": "AGPLv3", + "ignore": [ + "android", + "ios", + "boilerplate", + ".gitignore", + "*.podspec" + ], + "dependencies": { + "jquery": ">=1.8.3" + } +} diff --git a/ios/Hybridge/Hybridge/HYBBridge.h b/ios/Hybridge/Hybridge/HYBBridge.h index 8f094d1..de9cbea 100644 --- a/ios/Hybridge/Hybridge/HYBBridge.h +++ b/ios/Hybridge/Hybridge/HYBBridge.h @@ -21,9 +21,14 @@ @property (weak, nonatomic) NSObject *delegate; /** - Returns the native bridge version. + Returns the native bridge major version. */ -+ (NSInteger)version; ++ (NSInteger)majorVersion; + +/** + Returns the native bridge minor version. + */ ++ (NSInteger)minorVersion; /** Sets the active bridge. diff --git a/ios/Hybridge/Hybridge/HYBBridge.m b/ios/Hybridge/Hybridge/HYBBridge.m index ad2458a..e54e4d0 100644 --- a/ios/Hybridge/Hybridge/HYBBridge.m +++ b/ios/Hybridge/Hybridge/HYBBridge.m @@ -86,10 +86,14 @@ + (void)initialize { } } -+ (NSInteger)version { ++ (NSInteger)majorVersion { return 1; } ++ (NSInteger)minorVersion { + return 2; +} + static HYBBridge *activeBridge; + (void)setActiveBridge:(HYBBridge *)bridge { @@ -127,6 +131,7 @@ - (NSString *)prepareWebView:(UIWebView *)webView { @" window.HybridgeGlobal = {" @" isReady:true," @" version:%@," + @" versionMinor:%@," @" actions:%@," @" events:%@" @" };" @@ -139,7 +144,7 @@ - (NSString *)prepareWebView:(UIWebView *)webView { NSArray *events = @[HYBEventPause, HYBEventResume, HYBEventMessage, HYBEventReady]; NSString *eventsString = [NSString hyb_JSONStringWithObject:events]; - NSString *javascript = [NSString stringWithFormat:kFormat, @([[self class] version]), actionsString, eventsString]; + NSString *javascript = [NSString stringWithFormat:kFormat, @([[self class] majorVersion]), @([[self class] minorVersion]), actionsString, eventsString]; return [webView stringByEvaluatingJavaScriptFromString:javascript]; } diff --git a/ios/Hybridge/HybridgeTests/HYBBridgeTests.m b/ios/Hybridge/HybridgeTests/HYBBridgeTests.m index 4226448..85a8293 100644 --- a/ios/Hybridge/HybridgeTests/HYBBridgeTests.m +++ b/ios/Hybridge/HybridgeTests/HYBBridgeTests.m @@ -31,7 +31,11 @@ - (void)tearDown { } - (void)testVersion { - XCTAssertEqual((NSInteger)1, [HYBBridge version], @"should return the right version"); + XCTAssertEqual((NSInteger)1, [HYBBridge majorVersion], @"should return the right major version"); +} + +- (void)testVersionMinor { + XCTAssertEqual((NSInteger)2, [HYBBridge minorVersion], @"should return the right minor version"); } - (void)testActiveBridge { diff --git a/js/hybridge.js b/js/hybridge.js index 1fc5fa6..ff9685e 100644 --- a/js/hybridge.js +++ b/js/hybridge.js @@ -1,7 +1,7 @@ /*! - * tdigital-hybridge - v0.0.1 + * tdigital-hybridge - v1.2.0 * Bridge for mobile hybrid application between Javascript and native environment - * (iOS & Android) in an AMD fashion. + * (iOS & Android) * * Copyright 2013 Telefonica Investigación y Desarrollo, S.A.U * Licensed AfferoGPLv3 @@ -21,16 +21,21 @@ * please contact with contacto@tid.es */ -define([ - 'jquery' -], function ($) { - +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + root.Hybridge = factory(root.jQuery); + } +}(this, function ($) { 'use strict'; var READY_EVENT = 'ready'; var INIT_ACTION = 'init'; - var version = 1, initialized = false, + var version = 1, versionMinor = 2, initialized = false, xhr, method, logger, environment, debug, mockResponses, _events = {}, _actions = [], _errors, initModuleDef = $.Deferred(), initGlobalDef = $.Deferred(); @@ -76,7 +81,8 @@ define([ _send({ 'action' : INIT_ACTION, 'initialized' : deferredGlobal.initialized, - 'version' : version + 'version' : version, + 'versionMinor' : versionMinor }); } @@ -330,7 +336,8 @@ define([ window.HybridgeGlobal || setTimeout(function() { window.HybridgeGlobal = { isReady: true, - version: 1, + version: version, + versionMinor: versionMinor, actions: [INIT_ACTION, 'message'], events: [READY_EVENT, 'message'] }; @@ -464,6 +471,7 @@ define([ var Hybridge = { init: _init, version: version, + versionMinor: versionMinor, isNative: _isNative, isEnabled: _isEnabled, addListener: _addListener, @@ -500,4 +508,4 @@ define([ $.when(initModuleDef, initGlobalDef).then(_initNative); return Hybridge; -}); +}));