mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-27 04:42:51 +08:00
Implement the online events based Native->JS bridge.
This commit is contained in:
parent
7fa4515c28
commit
e239fd970f
@ -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);
|
||||||
|
@ -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,27 +33,33 @@ 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;
|
||||||
registeredListeners[0] = null;
|
|
||||||
registeredListeners[1] = new CallbackBridgeMode(webView);
|
public NativeToJsMessageQueue(CordovaWebView webView, CordovaInterface cordova) {
|
||||||
registeredListeners[2] = new LoadUrlBridgeMode(webView);
|
this.cordova = cordova;
|
||||||
reset();
|
this.webView = webView;
|
||||||
|
registeredListeners = new BridgeMode[4];
|
||||||
|
registeredListeners[0] = null;
|
||||||
|
registeredListeners[1] = new CallbackBridgeMode();
|
||||||
|
registeredListeners[2] = new LoadUrlBridgeMode();
|
||||||
|
registeredListeners[3] = new OnlineEventsBridgeMode();
|
||||||
|
reset();
|
||||||
// POLLING: 0,
|
// POLLING: 0,
|
||||||
// HANGING_GET: 1,
|
// HANGING_GET: 1,
|
||||||
// LOAD_URL: 2,
|
// LOAD_URL: 2,
|
||||||
@ -63,30 +71,30 @@ public class NativeToJsMessageQueue {
|
|||||||
* Changes the bridge mode.
|
* Changes the bridge mode.
|
||||||
*/
|
*/
|
||||||
public void setBridgeMode(int value) {
|
public void setBridgeMode(int value) {
|
||||||
if (value < 0 || value >= registeredListeners.length) {
|
if (value < 0 || value >= registeredListeners.length) {
|
||||||
Log.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value);
|
Log.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value);
|
||||||
} else {
|
} else {
|
||||||
if (value != activeListenerIndex) {
|
if (value != activeListenerIndex) {
|
||||||
Log.d(LOG_TAG, "Set native->JS mode to " + value);
|
Log.d(LOG_TAG, "Set native->JS mode to " + value);
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all messages and resets to the default bridge mode.
|
* Clears all messages and resets to the default bridge mode.
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
queue.clear();
|
queue.clear();
|
||||||
setBridgeMode(DEFAULT_BRIDGE_MODE);
|
setBridgeMode(DEFAULT_BRIDGE_MODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,17 +124,17 @@ public class NativeToJsMessageQueue {
|
|||||||
// Wrap each statement in a try/finally so that if one throws it does
|
// Wrap each statement in a try/finally so that if one throws it does
|
||||||
// not affect the next.
|
// not affect the next.
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (String message : queue) {
|
for (String message : queue) {
|
||||||
if (++i == length) {
|
if (++i == length) {
|
||||||
sb.append(message);
|
sb.append(message);
|
||||||
} else {
|
} else {
|
||||||
sb.append("try{")
|
sb.append("try{")
|
||||||
.append(message)
|
.append(message)
|
||||||
.append("}finally{");
|
.append("}finally{");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( i = 1; i < length; ++i) {
|
for ( i = 1; i < length; ++i) {
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
}
|
}
|
||||||
queue.clear();
|
queue.clear();
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@ -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) {
|
if (webView.callbackServer != null) {
|
||||||
this.webView = webView;
|
webView.callbackServer.onNativeToJsMessageAvailable(NativeToJsMessageQueue.this);
|
||||||
}
|
}
|
||||||
public void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue) {
|
|
||||||
if (webView.callbackServer != null) {
|
|
||||||
webView.callbackServer.onNativeToJsMessageAvailable(queue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user