Implement the online events based Native->JS bridge.

This commit is contained in:
Andrew Grieve 2012-08-21 14:15:04 -04:00
parent 7fa4515c28
commit e239fd970f
2 changed files with 79 additions and 62 deletions

View File

@ -198,7 +198,7 @@ public class CordovaWebView extends WebView {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("NewApi") @SuppressLint("NewApi")
private void setup() { private void setup() {
jsMessageQueue = new NativeToJsMessageQueue(this); jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
this.setInitialScale(0); this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false); this.setVerticalScrollBarEnabled(false);

View File

@ -20,6 +20,8 @@ package org.apache.cordova;
import java.util.LinkedList; import java.util.LinkedList;
import org.apache.cordova.api.CordovaInterface;
import android.util.Log; import android.util.Log;
/** /**
@ -31,26 +33,32 @@ public class NativeToJsMessageQueue {
// This must match the default value in incubator-cordova-js/lib/android/exec.js // This must match the default value in incubator-cordova-js/lib/android/exec.js
private static final int DEFAULT_BRIDGE_MODE = 1; private static final int DEFAULT_BRIDGE_MODE = 1;
/**
* The list of JavaScript statements to be sent to JavaScript.
*/
private LinkedList<String> queue = new LinkedList<String>();
/** /**
* The index into registeredListeners to treat as active. * The index into registeredListeners to treat as active.
*/ */
private int activeListenerIndex; private int activeListenerIndex;
/**
* The list of JavaScript statements to be sent to JavaScript.
*/
private final LinkedList<String> queue = new LinkedList<String>();
/** /**
* The array of listeners that can be used to send messages to JS. * The array of listeners that can be used to send messages to JS.
*/ */
private BridgeMode[] registeredListeners; private final BridgeMode[] registeredListeners;
public NativeToJsMessageQueue(CordovaWebView webView) { private final CordovaInterface cordova;
registeredListeners = new BridgeMode[3]; private final CordovaWebView webView;
public NativeToJsMessageQueue(CordovaWebView webView, CordovaInterface cordova) {
this.cordova = cordova;
this.webView = webView;
registeredListeners = new BridgeMode[4];
registeredListeners[0] = null; registeredListeners[0] = null;
registeredListeners[1] = new CallbackBridgeMode(webView); registeredListeners[1] = new CallbackBridgeMode();
registeredListeners[2] = new LoadUrlBridgeMode(webView); registeredListeners[2] = new LoadUrlBridgeMode();
registeredListeners[3] = new OnlineEventsBridgeMode();
reset(); reset();
// POLLING: 0, // POLLING: 0,
// HANGING_GET: 1, // HANGING_GET: 1,
@ -72,7 +80,7 @@ public class NativeToJsMessageQueue {
activeListenerIndex = value; activeListenerIndex = value;
BridgeMode activeListener = registeredListeners[value]; BridgeMode activeListener = registeredListeners[value];
if (!queue.isEmpty() && activeListener != null) { if (!queue.isEmpty() && activeListener != null) {
activeListener.onNativeToJsMessageAvailable(this); activeListener.onNativeToJsMessageAvailable();
} }
} }
} }
@ -140,37 +148,46 @@ public class NativeToJsMessageQueue {
synchronized (this) { synchronized (this) {
queue.add(statement); queue.add(statement);
if (registeredListeners[activeListenerIndex] != null) { if (registeredListeners[activeListenerIndex] != null) {
registeredListeners[activeListenerIndex].onNativeToJsMessageAvailable(this); registeredListeners[activeListenerIndex].onNativeToJsMessageAvailable();
} }
} }
} }
private interface BridgeMode { private interface BridgeMode {
void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue); void onNativeToJsMessageAvailable();
} }
/** Uses a local server to send messages to JS via an XHR */ /** Uses a local server to send messages to JS via an XHR */
private static class CallbackBridgeMode implements BridgeMode { private class CallbackBridgeMode implements BridgeMode {
private CordovaWebView webView; public void onNativeToJsMessageAvailable() {
public CallbackBridgeMode(CordovaWebView webView) {
this.webView = webView;
}
public void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue) {
if (webView.callbackServer != null) { if (webView.callbackServer != null) {
webView.callbackServer.onNativeToJsMessageAvailable(queue); webView.callbackServer.onNativeToJsMessageAvailable(NativeToJsMessageQueue.this);
} }
} }
} }
/** Uses webView.loadUrl("javascript:") to execute messages. */ /** Uses webView.loadUrl("javascript:") to execute messages. */
public static class LoadUrlBridgeMode implements BridgeMode { public class LoadUrlBridgeMode implements BridgeMode {
private CordovaWebView webView; public void onNativeToJsMessageAvailable() {
public LoadUrlBridgeMode(CordovaWebView webView) { webView.loadUrlNow("javascript:" + popAll());
this.webView = webView;
}
public void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue) {
webView.loadUrlNow("javascript:" + queue.popAll());
} }
} }
/** Uses online/offline events to tell the JS when to poll for messages. */
public class OnlineEventsBridgeMode implements BridgeMode {
boolean online = true;
final Runnable runnable = new Runnable() {
@Override
public void run() {
if (!queue.isEmpty()) {
online = !online;
webView.setNetworkAvailable(online);
}
}
};
public void onNativeToJsMessageAvailable() {
cordova.getActivity().runOnUiThread(runnable);
}
}
} }