diff --git a/src/android/com/nordnetab/cordova/ul/UniversalLinksPlugin.java b/src/android/com/nordnetab/cordova/ul/UniversalLinksPlugin.java index 4e61fd22..bce1d1d7 100644 --- a/src/android/com/nordnetab/cordova/ul/UniversalLinksPlugin.java +++ b/src/android/com/nordnetab/cordova/ul/UniversalLinksPlugin.java @@ -2,6 +2,7 @@ import android.content.Intent; import android.net.Uri; +import android.text.TextUtils; import android.util.Log; import com.nordnetab.cordova.ul.js.JSAction; @@ -17,7 +18,10 @@ import org.apache.cordova.PluginResult; import org.json.JSONException; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; /** * Created by Nikolay Demyankov on 09.09.15. @@ -30,9 +34,10 @@ public class UniversalLinksPlugin extends CordovaPlugin { // list of hosts, defined in config.xml private List supportedHosts; - // callback through which we will send events to JS - private CallbackContext defaultCallback; + // list of subscribers + private Map subscribers; + // stored message, that is captured on application launch private JSMessage storedMessage; // region Public API @@ -42,13 +47,21 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) { super.initialize(cordova, webView); supportedHosts = new ULConfigXmlParser(cordova.getActivity()).parse(); + + if (subscribers == null) { + subscribers = new HashMap(); + } + + handleIntent(cordova.getActivity().getIntent()); } @Override public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException { boolean isHandled = true; - if (JSAction.INIT.equals(action)) { - initJS(callbackContext); + if (JSAction.SUBSCRIBE.equals(action)) { + subscribeForEvent(args, callbackContext); + } else if (JSAction.UNSUBSCRIBE.equals(action)) { + unsubscribeFromEvent(args); } else { isHandled = false; } @@ -66,41 +79,86 @@ public void onNewIntent(Intent intent) { // region JavaScript methods /** - * Initialize plugin to communicate with JavaScript side. + * Add subscriber for the event. * - * @param callback default JS callback + * @param arguments arguments, passed from JS side + * @param callbackContext callback to use when event is captured */ - private void initJS(CallbackContext callback) { - setDefaultCallback(callback); - if (storedMessage != null) { - sendMessageToJs(storedMessage); - storedMessage = null; + private void subscribeForEvent(final CordovaArgs arguments, final CallbackContext callbackContext) { + final String eventName = getEventNameFromArguments(arguments); + if (TextUtils.isEmpty(eventName)) { return; } - handleIntent(cordova.getActivity().getIntent()); + subscribers.put(eventName, callbackContext); + tryToConsumeEvent(); } - private void setDefaultCallback(CallbackContext callback) { - this.defaultCallback = callback; + /** + * Remove subscriber from the event. + * + * @param arguments arguments, passed from JS side + */ + private void unsubscribeFromEvent(final CordovaArgs arguments) { + if (subscribers.size() == 0) { + return; + } + + final String eventName = getEventNameFromArguments(arguments); + if (TextUtils.isEmpty(eventName)) { + return; + } + + subscribers.remove(eventName); } /** - * Send message to JS side. + * Get event name from the cordova arguments. * - * @param message message to send - * @return true - if message is sent; otherwise - false + * @param arguments received arguments + * @return event name; null if non is found + */ + private String getEventNameFromArguments(final CordovaArgs arguments) { + String eventName = null; + try { + eventName = arguments.getString(0); + } catch (JSONException e) { + Log.d("UniversalLinks", "Failed to get event name from the JS arguments", e); + } + + return eventName; + } + + /** + * Try to send event to the subscribers. */ - private boolean sendMessageToJs(JSMessage message) { - if (defaultCallback == null) { - return false; + private void tryToConsumeEvent() { + if (subscribers.size() == 0 || storedMessage == null) { + return; } + final String storedEventName = storedMessage.getEventName(); + final Set> subscribersSet = subscribers.entrySet(); + for (Map.Entry subscriber : subscribersSet) { + final String eventName = subscriber.getKey(); + if (eventName.equals(storedEventName)) { + sendMessageToJs(storedMessage, subscriber.getValue()); + storedMessage = null; + break; + } + } + } + + /** + * Send message to JS side. + * + * @param message message to send + * @param callback to what callback we are sending the message + */ + private void sendMessageToJs(JSMessage message, CallbackContext callback) { final PluginResult result = new PluginResult(PluginResult.Status.OK, message); result.setKeepCallback(true); - defaultCallback.sendPluginResult(result); - - return true; + callback.sendPluginResult(result); } // endregion @@ -130,18 +188,13 @@ private void handleIntent(Intent intent) { // try to find host in the hosts list from the config.xml ULHost host = findHostByUrl(launchUri); if (host == null) { - Log.d("CUL", "Host " + launchUri.getHost() + " is not supported"); + Log.d("UniversalLinks", "Host " + launchUri.getHost() + " is not supported"); return; } - // send message to the JS side; - // if callback is not yet initialized - store message for later use; - final JSMessage message = new JSMessage(host, launchUri); - if (!sendMessageToJs(message)) { - storedMessage = message; - } else { - storedMessage = null; - } + // store message and try to consume it + storedMessage = new JSMessage(host, launchUri); + tryToConsumeEvent(); } /** diff --git a/src/android/com/nordnetab/cordova/ul/js/JSAction.java b/src/android/com/nordnetab/cordova/ul/js/JSAction.java index fbe99709..f194b077 100644 --- a/src/android/com/nordnetab/cordova/ul/js/JSAction.java +++ b/src/android/com/nordnetab/cordova/ul/js/JSAction.java @@ -8,8 +8,12 @@ public final class JSAction { /** - * Initialize native side to work with JS + * Subscribe to event. */ - public static final String INIT = "jsInitPlugin"; + public static final String SUBSCRIBE = "jsSubscribeForEvent"; + /** + * Unsubscribe from event. + */ + public static final String UNSUBSCRIBE = "jsUnsubscribeFromEvent"; } diff --git a/src/android/com/nordnetab/cordova/ul/model/JSMessage.java b/src/android/com/nordnetab/cordova/ul/model/JSMessage.java index 50dba102..5f0839ad 100644 --- a/src/android/com/nordnetab/cordova/ul/model/JSMessage.java +++ b/src/android/com/nordnetab/cordova/ul/model/JSMessage.java @@ -1,6 +1,7 @@ package com.nordnetab.cordova.ul.model; import android.net.Uri; +import android.util.Log; import org.json.JSONException; import org.json.JSONObject; @@ -62,6 +63,8 @@ private static final class JSDataKeys { public static final String ORIGIN = "url"; } + private String eventName; + /** * Constructor * @@ -73,18 +76,27 @@ public JSMessage(ULHost host, Uri originalUri) { setMessageData(host, originalUri); } + /** + * Getter for event name of this message. + * + * @return event name + */ + public String getEventName() { + return eventName; + } + // region Event name setters /** * Set event name for this message entry. */ private void setEventName(ULHost host, Uri originalUri) { - final String event = getEventName(host, originalUri); + eventName = getEventName(host, originalUri); try { - put(JSGeneralKeys.EVENT, event); + put(JSGeneralKeys.EVENT, eventName); } catch (JSONException e) { - e.printStackTrace(); + Log.d("UniversalLinks", "Failed to set event name", e); } } @@ -129,7 +141,7 @@ private void setMessageData(ULHost host, Uri originalUri) { put(JSGeneralKeys.DATA, dataObject); } catch (JSONException e) { - e.printStackTrace(); + Log.d("UniversalLinks", "Failed to set event data", e); } } diff --git a/src/android/com/nordnetab/cordova/ul/model/ULHost.java b/src/android/com/nordnetab/cordova/ul/model/ULHost.java index fb85377a..f286d61e 100644 --- a/src/android/com/nordnetab/cordova/ul/model/ULHost.java +++ b/src/android/com/nordnetab/cordova/ul/model/ULHost.java @@ -11,7 +11,7 @@ public class ULHost { // default event name, that is dispatched to JS if none was set to the host or path - private static final String DEFAULT_EVENT = "ul_didLaunchAppFromLink"; + private static final String DEFAULT_EVENT = "didLaunchAppFromLink"; // default scheme for the host private static final String DEFAULT_SCHEME = "http";