Merge branch 'master' into 4.0.x (keyboard events via PluginResult)

Conflicts:
	framework/src/org/apache/cordova/CordovaWebView.java
This commit is contained in:
Andrew Grieve 2014-12-30 23:30:42 -05:00
commit 61c4bb9888
4 changed files with 87 additions and 39 deletions

View File

@ -1,5 +1,5 @@
// Platform: android // Platform: android
// 1fc2526faa6197e1637ecb48ebe0f876f008ba0f // 12489aed3d93ecc98adfc2091fe566067f2d39fc
/* /*
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -509,9 +509,14 @@ function each(objects, func, context) {
function clobber(obj, key, value) { function clobber(obj, key, value) {
exports.replaceHookForTesting(obj, key); exports.replaceHookForTesting(obj, key);
obj[key] = value; var needsProperty = false;
try {
obj[key] = value;
} catch (e) {
needsProperty = true;
}
// Getters can only be overridden by getters. // Getters can only be overridden by getters.
if (obj[key] !== value) { if (needsProperty || obj[key] !== value) {
utils.defineGetter(obj, key, function() { utils.defineGetter(obj, key, function() {
return value; return value;
}); });
@ -1027,12 +1032,7 @@ function buildPayload(payload, message) {
payload.push(+message.slice(1)); payload.push(+message.slice(1));
} else if (payloadKind == 'A') { } else if (payloadKind == 'A') {
var data = message.slice(1); var data = message.slice(1);
var bytes = window.atob(data); payload.push(base64.toArrayBuffer(data));
var arraybuffer = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
arraybuffer[i] = bytes.charCodeAt(i);
}
payload.push(arraybuffer.buffer);
} else if (payloadKind == 'S') { } else if (payloadKind == 'S') {
payload.push(window.atob(message.slice(1))); payload.push(window.atob(message.slice(1)));
} else if (payloadKind == 'M') { } else if (payloadKind == 'M') {
@ -1167,6 +1167,7 @@ var cordova = require('cordova');
var modulemapper = require('cordova/modulemapper'); var modulemapper = require('cordova/modulemapper');
var platform = require('cordova/platform'); var platform = require('cordova/platform');
var pluginloader = require('cordova/pluginloader'); var pluginloader = require('cordova/pluginloader');
var utils = require('cordova/utils');
var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady]; var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
@ -1198,21 +1199,19 @@ function replaceNavigator(origNavigator) {
for (var key in origNavigator) { for (var key in origNavigator) {
if (typeof origNavigator[key] == 'function') { if (typeof origNavigator[key] == 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator); newNavigator[key] = origNavigator[key].bind(origNavigator);
} else { }
else {
(function(k) { (function(k) {
Object.defineProperty(newNavigator, k, { utils.defineGetterSetter(newNavigator,key,function() {
get: function() { return origNavigator[k];
return origNavigator[k]; });
}, })(key);
configurable: true,
enumerable: true
});
})(key);
} }
} }
} }
return newNavigator; return newNavigator;
} }
if (window.navigator) { if (window.navigator) {
window.navigator = replaceNavigator(window.navigator); window.navigator = replaceNavigator(window.navigator);
} }
@ -1293,6 +1292,7 @@ define("cordova/init_b", function(require, exports, module) {
var channel = require('cordova/channel'); var channel = require('cordova/channel');
var cordova = require('cordova'); var cordova = require('cordova');
var platform = require('cordova/platform'); var platform = require('cordova/platform');
var utils = require('cordova/utils');
var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady]; var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady];
@ -1327,16 +1327,13 @@ function replaceNavigator(origNavigator) {
for (var key in origNavigator) { for (var key in origNavigator) {
if (typeof origNavigator[key] == 'function') { if (typeof origNavigator[key] == 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator); newNavigator[key] = origNavigator[key].bind(origNavigator);
} else { }
else {
(function(k) { (function(k) {
Object.defineProperty(newNavigator, k, { utils.defineGetterSetter(newNavigator,key,function() {
get: function() { return origNavigator[k];
return origNavigator[k]; });
}, })(key);
configurable: true,
enumerable: true
});
})(key);
} }
} }
} }
@ -1385,7 +1382,7 @@ platform.bootstrap && platform.bootstrap();
* Create all cordova objects once native side is ready. * Create all cordova objects once native side is ready.
*/ */
channel.join(function() { channel.join(function() {
platform.initialize && platform.initialize(); platform.initialize && platform.initialize();
// Fire event to notify that all objects are created // Fire event to notify that all objects are created
@ -1546,11 +1543,27 @@ module.exports = {
// Let native code know we are all done on the JS side. // Let native code know we are all done on the JS side.
// Native code will then un-hide the WebView. // Native code will then un-hide the WebView.
channel.onCordovaReady.subscribe(function() { channel.onCordovaReady.subscribe(function() {
exec(onMessageFromNative, null, 'App', 'messageChannel', []);
exec(null, null, "App", "show", []); exec(null, null, "App", "show", []);
}); });
} }
}; };
function onMessageFromNative(msg) {
var cordova = require('cordova');
var action = msg.action;
switch (action)
{
case 'hidekeyboard':
case 'showkeyboard':
cordova.fireDocumentEvent(action);
break;
default:
throw new Error('Unknown event action ' + msg.action);
}
}
}); });
// file: src/android/plugin/android/app.js // file: src/android/plugin/android/app.js

View File

@ -125,7 +125,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova), this.cordova.getActivity().getPackageName()); bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova), this.cordova.getActivity().getPackageName());
initWebViewSettings(); initWebViewSettings();
pluginManager.addService("App", "org.apache.cordova.CoreAndroid"); pluginManager.addService(CoreAndroid.PLUGIN_NAME, "org.apache.cordova.CoreAndroid");
pluginManager.init(); pluginManager.init();
if (this.viewClient == null) { if (this.viewClient == null) {

View File

@ -41,8 +41,19 @@ import java.util.HashMap;
*/ */
public class CoreAndroid extends CordovaPlugin { public class CoreAndroid extends CordovaPlugin {
public static final String PLUGIN_NAME = "CoreAndroid";
protected static final String TAG = "CordovaApp"; protected static final String TAG = "CordovaApp";
private BroadcastReceiver telephonyReceiver; private BroadcastReceiver telephonyReceiver;
private CallbackContext messageChannel;
/**
* Send an event to be fired on the Javascript side.
*
* @param action The name of the event to be fired
*/
public void fireJavascriptEvent(String action) {
sendEventMessage(action);
}
/** /**
* Sets the context of the Command. This can then be used to do things like * Sets the context of the Command. This can then be used to do things like
@ -100,6 +111,11 @@ public class CoreAndroid extends CordovaPlugin {
else if (action.equals("exitApp")) { else if (action.equals("exitApp")) {
this.exitApp(); this.exitApp();
} }
else if (action.equals("messageChannel")) {
messageChannel = callbackContext;
return true;
}
callbackContext.sendPluginResult(new PluginResult(status, result)); callbackContext.sendPluginResult(new PluginResult(status, result));
return true; return true;
} catch (JSONException e) { } catch (JSONException e) {
@ -249,7 +265,7 @@ public class CoreAndroid extends CordovaPlugin {
public void exitApp() { public void exitApp() {
this.webView.getPluginManager().postMessage("exit", null); this.webView.getPluginManager().postMessage("exit", null);
} }
/** /**
* Listen for telephony events: RINGING, OFFHOOK and IDLE * Listen for telephony events: RINGING, OFFHOOK and IDLE
@ -290,6 +306,18 @@ public class CoreAndroid extends CordovaPlugin {
webView.getContext().registerReceiver(this.telephonyReceiver, intentFilter); webView.getContext().registerReceiver(this.telephonyReceiver, intentFilter);
} }
private void sendEventMessage(String action) {
JSONObject obj = new JSONObject();
try {
obj.put("action", action);
} catch (JSONException e) {
LOG.e(TAG, "Failed to create event message", e);
}
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, obj);
pluginResult.setKeepCallback(true);
messageChannel.sendPluginResult(pluginResult);
}
/* /*
* Unregister the receiver * Unregister the receiver
* *

View File

@ -18,10 +18,7 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.LOG;
import android.content.Context; import android.content.Context;
//import android.view.View.MeasureSpec;
import android.widget.LinearLayout; import android.widget.LinearLayout;
/** /**
@ -36,6 +33,7 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
private int screenWidth = 0; private int screenWidth = 0;
private int screenHeight = 0; private int screenHeight = 0;
private CordovaActivity app = null; private CordovaActivity app = null;
private CoreAndroid appPlugin = null;
public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) { public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) {
super(context); super(context);
@ -50,7 +48,7 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
* gets smaller fire a show keyboard event and when height gets bigger fire * gets smaller fire a show keyboard event and when height gets bigger fire
* a hide keyboard event. * a hide keyboard event.
* *
* Note: We are using app.postMessage so that this is more compatible with the API * Note: We are using the CoreAndroid plugin to send events over the bridge to Javascript
* *
* @param widthMeasureSpec * @param widthMeasureSpec
* @param heightMeasureSpec * @param heightMeasureSpec
@ -87,14 +85,12 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
// If the height as gotten bigger then we will assume the soft keyboard has // If the height as gotten bigger then we will assume the soft keyboard has
// gone away. // gone away.
else if (height > oldHeight) { else if (height > oldHeight) {
if (app != null) sendEvent("hidekeyboard");
app.appView.sendJavascript("cordova.fireDocumentEvent('hidekeyboard');");
} }
// If the height as gotten smaller then we will assume the soft keyboard has // If the height as gotten smaller then we will assume the soft keyboard has
// been displayed. // been displayed.
else if (height < oldHeight) { else if (height < oldHeight) {
if (app != null) sendEvent("showkeyboard");
app.appView.sendJavascript("cordova.fireDocumentEvent('showkeyboard');");
} }
// Update the old height for the next event // Update the old height for the next event
@ -102,4 +98,15 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
oldWidth = width; oldWidth = width;
} }
private void sendEvent(String event) {
if (appPlugin == null) {
appPlugin = (CoreAndroid)app.appView.getPluginManager().getPlugin(CoreAndroid.PLUGIN_NAME);
}
if (appPlugin == null) {
LOG.w(TAG, "Unable to fire event without existing plugin");
return;
}
appPlugin.fireJavascriptEvent(event);
}
} }