Merge commit and hacking on CordovaWebView

This commit is contained in:
Joe Bowser 2012-11-28 15:10:36 -08:00
commit a0d2b96de6
33 changed files with 1149 additions and 566 deletions

19
.gitignore vendored
View File

@ -4,28 +4,29 @@ gen
assets/www/cordova.js assets/www/cordova.js
framework/assets/www/.tmp* framework/assets/www/.tmp*
local.properties local.properties
framework/proguard.cfg framework/lib
framework/cordova.jar proguard.cfg
framework/cordova-*.jar proguard.cfg
framework/phonegap-*.jar proguard-project.txt
framework/bin framework/bin
framework/test/org/apache/cordova/*.class framework/test/org/apache/cordova/*.class
framework/assets/www/.DS_Store framework/assets/www/.DS_Store
framework/assets/www/cordova-*.js framework/assets/www/cordova-*.js
framework/assets/www/phonegap-*.js framework/assets/www/phonegap-*.js
framework/libs framework/libs
test/libs
example example
./test ./test
test/bin test/bin
test/assets/www/.tmp* test/assets/www/.tmp*
tmp/** tmp/**
*.tmp
test/libs/*.jar
bin/node_modules bin/node_modules
.metadata .metadata
*.bak
tmp/**/* tmp/**/*
*.swp
Thumbs.db Thumbs.db
Desktop.ini Desktop.ini
*.tmp
*.bak
*.swp
*.class
*.jar

View File

@ -1 +1 @@
2.2.0 2.3.0rc1

View File

@ -147,13 +147,13 @@ replace "s/__ACTIVITY__/${ACTIVITY}/g" "$MANIFEST_PATH"
replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH" replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
replace "s/__APILEVEL__/${API_LEVEL}/g" "$MANIFEST_PATH" replace "s/__APILEVEL__/${API_LEVEL}/g" "$MANIFEST_PATH"
# creating cordova folder and copying emulate/debug/log/launch scripts # creating cordova folder and copying run/build/log/launch scripts
mkdir "$PROJECT_PATH"/cordova mkdir "$PROJECT_PATH"/cordova
createAppInfoJar createAppInfoJar
cp "$BUILD_PATH"/bin/templates/cordova/appinfo.jar "$PROJECT_PATH"/cordova/appinfo.jar cp "$BUILD_PATH"/bin/templates/cordova/appinfo.jar "$PROJECT_PATH"/cordova/appinfo.jar
cp "$BUILD_PATH"/bin/templates/cordova/cordova "$PROJECT_PATH"/cordova/cordova cp "$BUILD_PATH"/bin/templates/cordova/cordova "$PROJECT_PATH"/cordova/cordova
cp "$BUILD_PATH"/bin/templates/cordova/debug "$PROJECT_PATH"/cordova/debug cp "$BUILD_PATH"/bin/templates/cordova/build "$PROJECT_PATH"/cordova/build
cp "$BUILD_PATH"/bin/templates/cordova/release "$PROJECT_PATH"/cordova/release
cp "$BUILD_PATH"/bin/templates/cordova/clean "$PROJECT_PATH"/cordova/clean cp "$BUILD_PATH"/bin/templates/cordova/clean "$PROJECT_PATH"/cordova/clean
cp "$BUILD_PATH"/bin/templates/cordova/log "$PROJECT_PATH"/cordova/log cp "$BUILD_PATH"/bin/templates/cordova/log "$PROJECT_PATH"/cordova/log
cp "$BUILD_PATH"/bin/templates/cordova/emulate "$PROJECT_PATH"/cordova/emulate cp "$BUILD_PATH"/bin/templates/cordova/run "$PROJECT_PATH"/cordova/run
cp "$BUILD_PATH"/bin/templates/cordova/BOOM "$PROJECT_PATH"/cordova/BOOM

View File

@ -198,10 +198,9 @@ exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\appinfo.jar ' + PRO
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.js ' + PROJECT_PATH + '\\cordova\\cordova.js /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.js ' + PROJECT_PATH + '\\cordova\\cordova.js /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.bat ' + PROJECT_PATH + '\\cordova\\cordova.bat /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.bat ' + PROJECT_PATH + '\\cordova\\cordova.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\clean.bat ' + PROJECT_PATH + '\\cordova\\clean.bat /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\clean.bat ' + PROJECT_PATH + '\\cordova\\clean.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\debug.bat ' + PROJECT_PATH + '\\cordova\\debug.bat /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\build.bat ' + PROJECT_PATH + '\\cordova\\build.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\log.bat ' + PROJECT_PATH + '\\cordova\\log.bat /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\log.bat ' + PROJECT_PATH + '\\cordova\\log.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\emulate.bat ' + PROJECT_PATH + '\\cordova\\emulate.bat /Y'); exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\run.bat ' + PROJECT_PATH + '\\cordova\\run.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\BOOM.bat ' + PROJECT_PATH + '\\cordova\\BOOM.bat /Y');
// interpolate the activity name and package // interpolate the activity name and package
WScript.Echo("Updating AndroidManifest.xml and Main Activity..."); WScript.Echo("Updating AndroidManifest.xml and Main Activity...");

View File

@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash "$CORDOVA_PATH"/cordova debug bash "$CORDOVA_PATH"/cordova build

View File

@ -15,4 +15,4 @@
:: specific language governing permissions and limitations :: specific language governing permissions and limitations
:: under the License. :: under the License.
%~dp0\cordova.bat BOOM %~dp0\cordova.bat build

View File

@ -17,12 +17,12 @@
#!/bin/bash #!/bin/bash
set -e
PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd ) PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd )
function check_devices { function check_devices {
local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}'` # FIXME
local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device`
if [ -z "$devices" ] ; then if [ -z "$devices" ] ; then
echo "1" echo "1"
else else
@ -37,7 +37,6 @@ function emulate {
# Do not launch an emulator if there is already one running or if a device is attached # Do not launch an emulator if there is already one running or if a device is attached
if [ $(check_devices) == 0 ] ; then if [ $(check_devices) == 0 ] ; then
echo "Device attached or emulator already running"
return return
fi fi
@ -62,8 +61,9 @@ function emulate {
do do
echo "$i) ${avd_list[$i]}" echo "$i) ${avd_list[$i]}"
done done
echo -n "> " read -t 5 -p "> " avd_id
read avd_id # default value if input timeout
if [ $avd_id -eq 1000 ] ; then avd_id=0 ; fi
done done
emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 & emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 &
fi fi
@ -78,14 +78,75 @@ function log {
adb logcat adb logcat
} }
function debug { function run {
if [ $(check_devices) == 0 ] ; then clean && emulate && wait_for_device && install && launch
ant debug install }
function install {
declare -a devices=($(adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device | cut -f 1))
local device_id="1000" #FIXME: hopefully user does not have 1000 AVDs
if [ ${#devices[@]} == 0 ]
then
# should not reach here. Emulator should launch or device should be attached
echo "Emulator not running or device not attached. Could not install debug package"
exit 70
fi
if [ ${#devices[@]} == 1 ]
then
export ANDROID_SERIAL=${devices[0]}
# User has more than 1 AVD
elif [ ${#devices[@]} -gt 1 ]
then
while [ -z ${devices[$device_id]} ]
do
echo "Choose from one of the following devices/emulators [0 to $((${#devices[@]}-1))]:"
for(( i = 0 ; i < ${#devices[@]} ; i++ ))
do
echo "$i) ${devices[$i]}"
done
read -t 5 -p "> " device_id
# default value if input timeout
if [ $device_id -eq 1000 ] ; then device_id=0 ; fi
done
export ANDROID_SERIAL=${devices[$device_id]}
fi
ant debug install
}
function build {
ant debug
}
function release {
ant release
}
function wait_for_device {
local i="0"
echo -n "Waiting for device..."
while [ $i -lt 300 ]
do
if [ $(check_devices) -eq 0 ]
then
break
else
sleep 1
i=$[i+1]
echo -n "."
fi
done
# Device timeout: emulator has not started in time or device not attached
if [ $i -eq 300 ]
then
echo "device timeout!"
exit 69
else else
ant debug echo "connected!"
echo "##################################################################"
echo "# Plug in your device or launch an emulator with cordova/emulate #"
echo "##################################################################"
fi fi
} }
@ -94,9 +155,5 @@ function launch {
adb shell am start -n $launch_str adb shell am start -n $launch_str
} }
function BOOM {
clean && debug && launch
}
# TODO parse arguments # TODO parse arguments
(cd "$PROJECT_PATH" && $1) (cd "$PROJECT_PATH" && $1)

View File

@ -34,17 +34,19 @@ function exec(command) {
return output; return output;
} }
function emulator_running() { function device_running() {
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll(); var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
if(local_devices.match(/emulator/)) { if(local_devices.match(/\w+\tdevice/)) {
WScript.Echo("Yes");
return true; return true;
} }
WScript.Echo("No");
return false; return false;
} }
function emulate() { function emulate() {
// don't run emulator if a device is plugged in or if emulator is already running // don't run emulator if a device is plugged in or if emulator is already running
if(emulator_running()) { if(device_running()) {
WScript.Echo("Device or Emulator already running!"); //WScript.Echo("Device or Emulator already running!");
return; return;
} }
var oExec = shell.Exec("%comspec% /c android.bat list avd"); var oExec = shell.Exec("%comspec% /c android.bat list avd");
@ -84,18 +86,18 @@ function emulate() {
} }
function clean() { function clean() {
WScript.Echo("Cleaning project...");
exec("%comspec% /c ant.bat clean -f "+ROOT+"\\build.xml 2>&1"); exec("%comspec% /c ant.bat clean -f "+ROOT+"\\build.xml 2>&1");
} }
function debug() { function build() {
if(emulator_running()) { WScript.Echo("Building project...");
exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1"); exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
} else { }
exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
WScript.Echo("##################################################################"); function install() {
WScript.Echo("# Plug in your device or launch an emulator with cordova/emulate #"); WScript.Echo("Building/Installing project...");
WScript.Echo("##################################################################"); exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
}
} }
function log() { function log() {
@ -103,14 +105,28 @@ function log() {
} }
function launch() { function launch() {
WScript.Echo("Launching app...");
var launch_str=exec("%comspec% /c java -jar "+ROOT+"\\cordova\\appinfo.jar "+ROOT+"\\AndroidManifest.xml"); var launch_str=exec("%comspec% /c java -jar "+ROOT+"\\cordova\\appinfo.jar "+ROOT+"\\AndroidManifest.xml");
//WScript.Echo(launch_str); //WScript.Echo(launch_str);
exec("%comspec% /c adb shell am start -n "+launch_str+" 2>&1"); exec("%comspec% /c adb shell am start -n "+launch_str+" 2>&1");
} }
function BOOM() { function run() {
var i=0;
clean(); clean();
debug(); emulate();
WScript.Stdout.Write('Waiting for device...');
while(!device_running() && i < 300) {
WScript.Stdout.Write('.');
WScript.sleep(1000);
i += 1;
}
if(i == 300) {
WScript.Stderr.WriteLine("device/emulator timeout!");
} else {
WScript.Stdout.WriteLine("connected!");
}
install();
launch(); launch();
} }
var args = WScript.Arguments; var args = WScript.Arguments;

View File

@ -1,18 +0,0 @@
:: Licensed to the Apache Software Foundation (ASF) under one
:: or more contributor license agreements. See the NOTICE file
:: distributed with this work for additional information
:: regarding copyright ownership. The ASF licenses this file
:: to you under the Apache License, Version 2.0 (the
:: "License"); you may not use this file except in compliance
:: with the License. You may obtain a copy of the License at
::
:: http://www.apache.org/licenses/LICENSE-2.0
::
:: Unless required by applicable law or agreed to in writing,
:: software distributed under the License is distributed on an
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
:: KIND, either express or implied. See the License for the
:: specific language governing permissions and limitations
:: under the License.
%~dp0\cordova.bat debug

View File

@ -1 +0,0 @@
%~dp0\cordova.bat emulate

View File

@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash "$CORDOVA_PATH"/cordova emulate bash "$CORDOVA_PATH"/cordova release

View File

@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
bash $CORDOVA_PATH/cordova BOOM bash "$CORDOVA_PATH"/cordova run

View File

@ -0,0 +1 @@
%~dp0\cordova.bat run

View File

@ -33,7 +33,7 @@
<p class="event received">Device is Ready</p> <p class="event received">Device is Ready</p>
</div> </div>
</div> </div>
<script type="text/javascript" src="cordova-2.2.0.js"></script> <script type="text/javascript" src="cordova-2.3.0rc1.js"></script>
<script type="text/javascript" src="js/index.js"></script> <script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript"> <script type="text/javascript">
app.initialize(); app.initialize();

View File

@ -1,6 +1,6 @@
// commit 02b91c5313ff37d74a58f71775170afd360f4a1f // commit 54335c8f70223b053f4c039185d13cb95801d043
// File generated at :: Wed Oct 31 2012 10:40:25 GMT-0700 (PDT) // File generated at :: Mon Nov 26 2012 16:05:15 GMT-0500 (EST)
/* /*
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
@ -314,6 +314,65 @@ channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
module.exports = cordova; module.exports = cordova;
});
// file: lib/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) {
var exec = require('cordova/exec');
var moduleExports = module.exports;
var typeMap = {
'A': 'Array',
'D': 'Date',
'N': 'Number',
'S': 'String',
'F': 'Function',
'O': 'Object'
};
function extractParamName(callee, argIndex) {
return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
}
function checkArgs(spec, functionName, args, opt_callee) {
if (!moduleExports.enableChecks) {
return;
}
var errMsg = null;
var type;
for (var i = 0; i < spec.length; ++i) {
var c = spec.charAt(i),
cUpper = c.toUpperCase(),
arg = args[i];
// Asterix means allow anything.
if (c == '*') {
continue;
}
type = Object.prototype.toString.call(arg).slice(8, -1);
if ((arg === null || arg === undefined) && c == cUpper) {
continue;
}
if (type != typeMap[cUpper]) {
errMsg = 'Expected ' + typeMap[cUpper];
break;
}
}
if (errMsg) {
errMsg += ', but got ' + type + '.';
errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
// Don't log when running jake test.
if (typeof jasmine == 'undefined') {
console.error(errMsg);
}
throw TypeError(errMsg);
}
}
moduleExports.checkArgs = checkArgs;
moduleExports.enableChecks = true;
}); });
// file: lib/common/builder.js // file: lib/common/builder.js
@ -329,14 +388,24 @@ function each(objects, func, context) {
} }
} }
function clobber(obj, key, value) {
obj[key] = value;
// Getters can only be overridden by getters.
if (obj[key] !== value) {
utils.defineGetter(obj, key, function() {
return value;
});
}
}
function assignOrWrapInDeprecateGetter(obj, key, value, message) { function assignOrWrapInDeprecateGetter(obj, key, value, message) {
if (message) { if (message) {
utils.defineGetter(obj, key, function() { utils.defineGetter(obj, key, function() {
window.console && console.log(message); console.log(message);
return value; return value;
}); });
} else { } else {
obj[key] = value; clobber(obj, key, value);
} }
} }
@ -395,8 +464,11 @@ function recursiveMerge(target, src) {
// If the target object is a constructor override off prototype. // If the target object is a constructor override off prototype.
target.prototype[prop] = src[prop]; target.prototype[prop] = src[prop];
} else { } else {
target[prop] = typeof src[prop] === 'object' ? recursiveMerge( if (typeof src[prop] === 'object') {
target[prop], src[prop]) : src[prop]; target[prop] = recursiveMerge(target[prop], src[prop]);
} else {
clobber(target, prop, src[prop]);
}
} }
} }
} }
@ -404,18 +476,14 @@ function recursiveMerge(target, src) {
} }
module.exports = { module.exports = {
build: function (objects) { buildIntoButDoNotClobber: function(objects, target) {
return { include(target, objects, false, false);
intoButDoNotClobber: function (target) { },
include(target, objects, false, false); buildIntoAndClobber: function(objects, target) {
}, include(target, objects, true, false);
intoAndClobber: function(target) { },
include(target, objects, true, false); buildIntoAndMerge: function(objects, target) {
}, include(target, objects, true, true);
intoAndMerge: function(target) {
include(target, objects, true, true);
}
};
} }
}; };
@ -701,7 +769,7 @@ module.exports = {
define("cordova/common", function(require, exports, module) { define("cordova/common", function(require, exports, module) {
module.exports = { module.exports = {
objects: { defaults: {
cordova: { cordova: {
path: 'cordova', path: 'cordova',
children: { children: {
@ -720,6 +788,9 @@ module.exports = {
} }
} }
}, },
open : {
path: 'cordova/plugin/InAppBrowser'
},
navigator: { navigator: {
children: { children: {
notification: { notification: {
@ -737,9 +808,6 @@ module.exports = {
compass:{ compass:{
path: 'cordova/plugin/compass' path: 'cordova/plugin/compass'
}, },
connection: {
path: 'cordova/plugin/network'
},
contacts: { contacts: {
path: 'cordova/plugin/contacts' path: 'cordova/plugin/contacts'
}, },
@ -907,6 +975,15 @@ module.exports = {
resolveLocalFileSystemURI:{ resolveLocalFileSystemURI:{
path: 'cordova/plugin/resolveLocalFileSystemURI' path: 'cordova/plugin/resolveLocalFileSystemURI'
} }
},
clobbers: {
navigator: {
children: {
connection: {
path: 'cordova/plugin/network'
}
}
}
} }
}; };
@ -961,6 +1038,7 @@ var cordova = require('cordova'),
function androidExec(success, fail, service, action, args) { function androidExec(success, fail, service, action, args) {
// Set default bridge modes if they have not already been set. // Set default bridge modes if they have not already been set.
// By default, we use the failsafe, since addJavascriptInterface breaks too often
if (jsToNativeBridgeMode === undefined) { if (jsToNativeBridgeMode === undefined) {
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT); androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
} }
@ -1199,7 +1277,7 @@ module.exports = {
exec(null, null, "App", "show", []); exec(null, null, "App", "show", []);
}, [channel.onCordovaReady]); }, [channel.onCordovaReady]);
}, },
objects: { clobbers: {
navigator: { navigator: {
children: { children: {
app:{ app:{
@ -1218,6 +1296,9 @@ module.exports = {
}, },
MediaError: { // exists natively on Android WebView on Android 4.x MediaError: { // exists natively on Android WebView on Android 4.x
path: "cordova/plugin/MediaError" path: "cordova/plugin/MediaError"
},
open: {
path: "cordova/plugin/InAppBrowser"
} }
}, },
merges: { merges: {
@ -3237,6 +3318,25 @@ module.exports = GlobalizationError;
}); });
// file: lib/common/plugin/InAppBrowser.js
define("cordova/plugin/InAppBrowser", function(require, exports, module) {
var exec = require('cordova/exec');
var InAppBrowser = {
open : function(strUrl, strWindowName, strWindowFeatures) {
exec(null, null, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
return InAppBrowser;
},
close : function() {
exec(null, null, "InAppBrowser", "close", []);
}
};
module.exports = InAppBrowser.open;
});
// file: lib/common/plugin/LocalFileSystem.js // file: lib/common/plugin/LocalFileSystem.js
define("cordova/plugin/LocalFileSystem", function(require, exports, module) { define("cordova/plugin/LocalFileSystem", function(require, exports, module) {
@ -3673,7 +3773,8 @@ define("cordova/plugin/accelerometer", function(require, exports, module) {
* This class provides access to device accelerometer data. * This class provides access to device accelerometer data.
* @constructor * @constructor
*/ */
var utils = require("cordova/utils"), var argscheck = require('cordova/argscheck'),
utils = require("cordova/utils"),
exec = require("cordova/exec"), exec = require("cordova/exec"),
Acceleration = require('cordova/plugin/Acceleration'); Acceleration = require('cordova/plugin/Acceleration');
@ -3737,10 +3838,7 @@ var accelerometer = {
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL) * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
*/ */
getCurrentAcceleration: function(successCallback, errorCallback, options) { getCurrentAcceleration: function(successCallback, errorCallback, options) {
// successCallback required argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
if (typeof successCallback !== "function") {
throw "getCurrentAcceleration must be called with at least a success callback function as first parameter.";
}
var p; var p;
var win = function(a) { var win = function(a) {
@ -3749,7 +3847,7 @@ var accelerometer = {
}; };
var fail = function(e) { var fail = function(e) {
removeListeners(p); removeListeners(p);
errorCallback(e); errorCallback && errorCallback(e);
}; };
p = createCallbackPair(win, fail); p = createCallbackPair(win, fail);
@ -3769,20 +3867,16 @@ var accelerometer = {
* @return String The watch id that must be passed to #clearWatch to stop watching. * @return String The watch id that must be passed to #clearWatch to stop watching.
*/ */
watchAcceleration: function(successCallback, errorCallback, options) { watchAcceleration: function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
// Default interval (10 sec) // Default interval (10 sec)
var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000; var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
// successCallback required
if (typeof successCallback !== "function") {
throw "watchAcceleration must be called with at least a success callback function as first parameter.";
}
// Keep reference to watch id, and report accel readings as often as defined in frequency // Keep reference to watch id, and report accel readings as often as defined in frequency
var id = utils.createUUID(); var id = utils.createUUID();
var p = createCallbackPair(function(){}, function(e) { var p = createCallbackPair(function(){}, function(e) {
removeListeners(p); removeListeners(p);
errorCallback(e); errorCallback && errorCallback(e);
}); });
listeners.push(p); listeners.push(p);
@ -3798,7 +3892,7 @@ var accelerometer = {
if (running) { if (running) {
// If we're already running then immediately invoke the success callback // If we're already running then immediately invoke the success callback
// but only if we have retrieved a value, sample code does not check for null ... // but only if we have retrieved a value, sample code does not check for null ...
if(accel) { if (accel) {
successCallback(accel); successCallback(accel);
} }
} else { } else {
@ -4592,7 +4686,8 @@ module.exports = new Capture();
// file: lib/common/plugin/compass.js // file: lib/common/plugin/compass.js
define("cordova/plugin/compass", function(require, exports, module) { define("cordova/plugin/compass", function(require, exports, module) {
var exec = require('cordova/exec'), var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
utils = require('cordova/utils'), utils = require('cordova/utils'),
CompassHeading = require('cordova/plugin/CompassHeading'), CompassHeading = require('cordova/plugin/CompassHeading'),
CompassError = require('cordova/plugin/CompassError'), CompassError = require('cordova/plugin/CompassError'),
@ -4607,23 +4702,13 @@ var exec = require('cordova/exec'),
* @param {CompassOptions} options The options for getting the heading data (not used). * @param {CompassOptions} options The options for getting the heading data (not used).
*/ */
getCurrentHeading:function(successCallback, errorCallback, options) { getCurrentHeading:function(successCallback, errorCallback, options) {
// successCallback required argscheck.checkArgs('fFO', 'compass.getCurrentHeading', arguments);
if (typeof successCallback !== "function") {
console.log("Compass Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Compass Error: errorCallback is not a function");
return;
}
var win = function(result) { var win = function(result) {
var ch = new CompassHeading(result.magneticHeading, result.trueHeading, result.headingAccuracy, result.timestamp); var ch = new CompassHeading(result.magneticHeading, result.trueHeading, result.headingAccuracy, result.timestamp);
successCallback(ch); successCallback(ch);
}; };
var fail = function(code) { var fail = errorCallback && function(code) {
var ce = new CompassError(code); var ce = new CompassError(code);
errorCallback(ce); errorCallback(ce);
}; };
@ -4643,22 +4728,11 @@ var exec = require('cordova/exec'),
* specifies to watch via a distance filter rather than time. * specifies to watch via a distance filter rather than time.
*/ */
watchHeading:function(successCallback, errorCallback, options) { watchHeading:function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'compass.watchHeading', arguments);
// Default interval (100 msec) // Default interval (100 msec)
var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100; var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100;
var filter = (options !== undefined && options.filter !== undefined) ? options.filter : 0; var filter = (options !== undefined && options.filter !== undefined) ? options.filter : 0;
// successCallback required
if (typeof successCallback !== "function") {
console.log("Compass Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Compass Error: errorCallback is not a function");
return;
}
var id = utils.createUUID(); var id = utils.createUUID();
if (filter > 0) { if (filter > 0) {
// is an iOS request for watch by filter, no timer needed // is an iOS request for watch by filter, no timer needed
@ -4682,8 +4756,8 @@ var exec = require('cordova/exec'),
// Stop javascript timer & remove from timer list // Stop javascript timer & remove from timer list
if (id && timers[id]) { if (id && timers[id]) {
if (timers[id] != "iOS") { if (timers[id] != "iOS") {
clearInterval(timers[id]); clearInterval(timers[id]);
} else { } else {
// is iOS watch by filter so call into device to stop // is iOS watch by filter so call into device to stop
exec(null, null, "Compass", "stopHeading", []); exec(null, null, "Compass", "stopHeading", []);
} }
@ -4871,7 +4945,8 @@ for (var key in console) {
// file: lib/common/plugin/contacts.js // file: lib/common/plugin/contacts.js
define("cordova/plugin/contacts", function(require, exports, module) { define("cordova/plugin/contacts", function(require, exports, module) {
var exec = require('cordova/exec'), var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
ContactError = require('cordova/plugin/ContactError'), ContactError = require('cordova/plugin/ContactError'),
utils = require('cordova/utils'), utils = require('cordova/utils'),
Contact = require('cordova/plugin/Contact'); Contact = require('cordova/plugin/Contact');
@ -4890,13 +4965,9 @@ var contacts = {
* @return array of Contacts matching search criteria * @return array of Contacts matching search criteria
*/ */
find:function(fields, successCB, errorCB, options) { find:function(fields, successCB, errorCB, options) {
if (!successCB) { argscheck.checkArgs('afFO', 'contacts.find', arguments);
throw new TypeError("You must specify a success callback for the find command."); if (!fields.length) {
} errorCB && errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
if (!fields || (utils.isArray(fields) && fields.length === 0)) {
if (typeof errorCB === "function") {
errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
}
} else { } else {
var win = function(result) { var win = function(result) {
var cs = []; var cs = [];
@ -4917,9 +4988,9 @@ var contacts = {
* @returns new Contact object * @returns new Contact object
*/ */
create:function(properties) { create:function(properties) {
var i; argscheck.checkArgs('O', 'contacts.create', arguments);
var contact = new Contact(); var contact = new Contact();
for (i in properties) { for (var i in properties) {
if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) { if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
contact[i] = properties[i]; contact[i] = properties[i];
} }
@ -4935,7 +5006,8 @@ module.exports = contacts;
// file: lib/common/plugin/device.js // file: lib/common/plugin/device.js
define("cordova/plugin/device", function(require, exports, module) { define("cordova/plugin/device", function(require, exports, module) {
var channel = require('cordova/channel'), var argscheck = require('cordova/argscheck'),
channel = require('cordova/channel'),
utils = require('cordova/utils'), utils = require('cordova/utils'),
exec = require('cordova/exec'); exec = require('cordova/exec');
@ -4954,6 +5026,7 @@ function Device() {
this.name = null; this.name = null;
this.uuid = null; this.uuid = null;
this.cordova = null; this.cordova = null;
this.model = null;
var me = this; var me = this;
@ -4965,6 +5038,7 @@ function Device() {
me.name = info.name; me.name = info.name;
me.uuid = info.uuid; me.uuid = info.uuid;
me.cordova = info.cordova; me.cordova = info.cordova;
me.model = info.model;
channel.onCordovaInfoReady.fire(); channel.onCordovaInfoReady.fire();
},function(e) { },function(e) {
me.available = false; me.available = false;
@ -4980,20 +5054,7 @@ function Device() {
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
*/ */
Device.prototype.getInfo = function(successCallback, errorCallback) { Device.prototype.getInfo = function(successCallback, errorCallback) {
argscheck.checkArgs('fF', 'Device.getInfo', arguments);
// successCallback required
if (typeof successCallback !== "function") {
console.log("Device Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Device Error: errorCallback is not a function");
return;
}
// Get info
exec(successCallback, errorCallback, "Device", "getDeviceInfo", []); exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
}; };
@ -5024,7 +5085,8 @@ module.exports = function(successCallback, errorCallback, message, forceAsync) {
// file: lib/common/plugin/geolocation.js // file: lib/common/plugin/geolocation.js
define("cordova/plugin/geolocation", function(require, exports, module) { define("cordova/plugin/geolocation", function(require, exports, module) {
var utils = require('cordova/utils'), var argscheck = require('cordova/argscheck'),
utils = require('cordova/utils'),
exec = require('cordova/exec'), exec = require('cordova/exec'),
PositionError = require('cordova/plugin/PositionError'), PositionError = require('cordova/plugin/PositionError'),
Position = require('cordova/plugin/Position'); Position = require('cordova/plugin/Position');
@ -5081,9 +5143,7 @@ var geolocation = {
* @param {PositionOptions} options The options for getting the position data. (OPTIONAL) * @param {PositionOptions} options The options for getting the position data. (OPTIONAL)
*/ */
getCurrentPosition:function(successCallback, errorCallback, options) { getCurrentPosition:function(successCallback, errorCallback, options) {
if (arguments.length === 0) { argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments);
throw new Error("getCurrentPosition must be called with at least one argument.");
}
options = parseParameters(options); options = parseParameters(options);
// Timer var that will fire an error callback if no position is retrieved from native // Timer var that will fire an error callback if no position is retrieved from native
@ -5159,9 +5219,7 @@ var geolocation = {
* @return String The watch id that must be passed to #clearWatch to stop watching. * @return String The watch id that must be passed to #clearWatch to stop watching.
*/ */
watchPosition:function(successCallback, errorCallback, options) { watchPosition:function(successCallback, errorCallback, options) {
if (arguments.length === 0) { argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments);
throw new Error("watchPosition must be called with at least one argument.");
}
options = parseParameters(options); options = parseParameters(options);
var id = utils.createUUID(); var id = utils.createUUID();
@ -5223,7 +5281,8 @@ module.exports = geolocation;
// file: lib/common/plugin/globalization.js // file: lib/common/plugin/globalization.js
define("cordova/plugin/globalization", function(require, exports, module) { define("cordova/plugin/globalization", function(require, exports, module) {
var exec = require('cordova/exec'), var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
GlobalizationError = require('cordova/plugin/GlobalizationError'); GlobalizationError = require('cordova/plugin/GlobalizationError');
var globalization = { var globalization = {
@ -5246,18 +5305,7 @@ var globalization = {
* function () {}); * function () {});
*/ */
getPreferredLanguage:function(successCB, failureCB) { getPreferredLanguage:function(successCB, failureCB) {
// successCallback required argscheck.checkArgs('fF', 'Globalization.getPreferredLanguage', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getPreferredLanguage Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getPreferredLanguage Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization","getPreferredLanguage", []); exec(successCB, failureCB, "Globalization","getPreferredLanguage", []);
}, },
@ -5279,17 +5327,7 @@ getPreferredLanguage:function(successCB, failureCB) {
* function () {}); * function () {});
*/ */
getLocaleName:function(successCB, failureCB) { getLocaleName:function(successCB, failureCB) {
// successCallback required argscheck.checkArgs('fF', 'Globalization.getLocaleName', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getLocaleName Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getLocaleName Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization","getLocaleName", []); exec(successCB, failureCB, "Globalization","getLocaleName", []);
}, },
@ -5320,27 +5358,9 @@ getLocaleName:function(successCB, failureCB) {
* {formatLength:'short'}); * {formatLength:'short'});
*/ */
dateToString:function(date, successCB, failureCB, options) { dateToString:function(date, successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('dfFO', 'Globalization.dateToString', arguments);
if (typeof successCB != "function") { var dateValue = date.valueOf();
console.log("Globalization.dateToString Error: successCB is not a function"); exec(successCB, failureCB, "Globalization", "dateToString", [{"date": dateValue, "options": options}]);
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.dateToString Error: failureCB is not a function");
return;
}
if (date instanceof Date){
var dateValue;
dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "dateToString", [{"date": dateValue, "options": options}]);
}
else {
console.log("Globalization.dateToString Error: date is not a Date object");
}
}, },
@ -5380,23 +5400,8 @@ dateToString:function(date, successCB, failureCB, options) {
* {selector:'date'}); * {selector:'date'});
*/ */
stringToDate:function(dateString, successCB, failureCB, options) { stringToDate:function(dateString, successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('sfFO', 'Globalization.stringToDate', arguments);
if (typeof successCB != "function") { exec(successCB, failureCB, "Globalization", "stringToDate", [{"dateString": dateString, "options": options}]);
console.log("Globalization.stringToDate Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.stringToDate Error: failureCB is not a function");
return;
}
if (typeof dateString == "string"){
exec(successCB, failureCB, "Globalization", "stringToDate", [{"dateString": dateString, "options": options}]);
}
else {
console.log("Globalization.stringToDate Error: dateString is not a string");
}
}, },
@ -5433,18 +5438,7 @@ stringToDate:function(dateString, successCB, failureCB, options) {
* {formatLength:'short'}); * {formatLength:'short'});
*/ */
getDatePattern:function(successCB, failureCB, options) { getDatePattern:function(successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('fFO', 'Globalization.getDatePattern', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getDatePattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getDatePattern Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization", "getDatePattern", [{"options": options}]); exec(successCB, failureCB, "Globalization", "getDatePattern", [{"options": options}]);
}, },
@ -5475,17 +5469,7 @@ getDatePattern:function(successCB, failureCB, options) {
* function () {}); * function () {});
*/ */
getDateNames:function(successCB, failureCB, options) { getDateNames:function(successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('fFO', 'Globalization.getDateNames', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getDateNames Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getDateNames Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization", "getDateNames", [{"options": options}]); exec(successCB, failureCB, "Globalization", "getDateNames", [{"options": options}]);
}, },
@ -5510,28 +5494,9 @@ getDateNames:function(successCB, failureCB, options) {
* function () {}); * function () {});
*/ */
isDayLightSavingsTime:function(date, successCB, failureCB) { isDayLightSavingsTime:function(date, successCB, failureCB) {
// successCallback required argscheck.checkArgs('dfF', 'Globalization.isDayLightSavingsTime', arguments);
if (typeof successCB != "function") { var dateValue = date.valueOf();
console.log("Globalization.isDayLightSavingsTime Error: successCB is not a function"); exec(successCB, failureCB, "Globalization", "isDayLightSavingsTime", [{"date": dateValue}]);
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.isDayLightSavingsTime Error: failureCB is not a function");
return;
}
if (date instanceof Date){
var dateValue;
dateValue = date.valueOf();
exec(successCB, failureCB, "Globalization", "isDayLightSavingsTime", [{"date": dateValue}]);
}
else {
console.log("Globalization.isDayLightSavingsTime Error: date is not a Date object");
}
}, },
/** /**
@ -5553,18 +5518,7 @@ isDayLightSavingsTime:function(date, successCB, failureCB) {
* function () {}); * function () {});
*/ */
getFirstDayOfWeek:function(successCB, failureCB) { getFirstDayOfWeek:function(successCB, failureCB) {
// successCallback required argscheck.checkArgs('fF', 'Globalization.getFirstDayOfWeek', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getFirstDayOfWeek Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getFirstDayOfWeek Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization", "getFirstDayOfWeek", []); exec(successCB, failureCB, "Globalization", "getFirstDayOfWeek", []);
}, },
@ -5593,24 +5547,8 @@ getFirstDayOfWeek:function(successCB, failureCB) {
* {type:'decimal'}); * {type:'decimal'});
*/ */
numberToString:function(number, successCB, failureCB, options) { numberToString:function(number, successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('nfFO', 'Globalization.numberToString', arguments);
if (typeof successCB != "function") { exec(successCB, failureCB, "Globalization", "numberToString", [{"number": number, "options": options}]);
console.log("Globalization.numberToString Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.numberToString Error: failureCB is not a function");
return;
}
if(typeof number == "number") {
exec(successCB, failureCB, "Globalization", "numberToString", [{"number": number, "options": options}]);
}
else {
console.log("Globalization.numberToString Error: number is not a number");
}
}, },
/** /**
@ -5637,24 +5575,8 @@ numberToString:function(number, successCB, failureCB, options) {
* function () { alert('Error parsing number');}); * function () { alert('Error parsing number');});
*/ */
stringToNumber:function(numberString, successCB, failureCB, options) { stringToNumber:function(numberString, successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('sfFO', 'Globalization.stringToNumber', arguments);
if (typeof successCB != "function") { exec(successCB, failureCB, "Globalization", "stringToNumber", [{"numberString": numberString, "options": options}]);
console.log("Globalization.stringToNumber Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.stringToNumber Error: failureCB is not a function");
return;
}
if(typeof numberString == "string") {
exec(successCB, failureCB, "Globalization", "stringToNumber", [{"numberString": numberString, "options": options}]);
}
else {
console.log("Globalization.stringToNumber Error: numberString is not a string");
}
}, },
/** /**
@ -5690,18 +5612,7 @@ stringToNumber:function(numberString, successCB, failureCB, options) {
* function () {}); * function () {});
*/ */
getNumberPattern:function(successCB, failureCB, options) { getNumberPattern:function(successCB, failureCB, options) {
// successCallback required argscheck.checkArgs('fFO', 'Globalization.getNumberPattern', arguments);
if (typeof successCB != "function") {
console.log("Globalization.getNumberPattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getNumberPattern Error: failureCB is not a function");
return;
}
exec(successCB, failureCB, "Globalization", "getNumberPattern", [{"options": options}]); exec(successCB, failureCB, "Globalization", "getNumberPattern", [{"options": options}]);
}, },
@ -5733,24 +5644,8 @@ getNumberPattern:function(successCB, failureCB, options) {
* function () {}); * function () {});
*/ */
getCurrencyPattern:function(currencyCode, successCB, failureCB) { getCurrencyPattern:function(currencyCode, successCB, failureCB) {
// successCallback required argscheck.checkArgs('sfF', 'Globalization.getCurrencyPattern', arguments);
if (typeof successCB != "function") { exec(successCB, failureCB, "Globalization", "getCurrencyPattern", [{"currencyCode": currencyCode}]);
console.log("Globalization.getCurrencyPattern Error: successCB is not a function");
return;
}
// errorCallback required
if (typeof failureCB != "function") {
console.log("Globalization.getCurrencyPattern Error: failureCB is not a function");
return;
}
if(typeof currencyCode == "string") {
exec(successCB, failureCB, "Globalization", "getCurrencyPattern", [{"currencyCode": currencyCode}]);
}
else {
console.log("Globalization.getCurrencyPattern Error: currencyCode is not a currency code");
}
} }
}; };
@ -6004,49 +5899,9 @@ if (typeof navigator != 'undefined') {
}); });
} }
var NetworkConnection = function () { function NetworkConnection() {
this.type = null; this.type = 'unknown';
this._firstRun = true; }
this._timer = null;
this.timeout = 500;
var me = this;
channel.onCordovaReady.subscribe(function() {
me.getInfo(function (info) {
me.type = info;
if (info === "none") {
// set a timer if still offline at the end of timer send the offline event
me._timer = setTimeout(function(){
cordova.fireDocumentEvent("offline");
me._timer = null;
}, me.timeout);
} else {
// If there is a current offline event pending clear it
if (me._timer !== null) {
clearTimeout(me._timer);
me._timer = null;
}
cordova.fireDocumentEvent("online");
}
// should only fire this once
if (me._firstRun) {
me._firstRun = false;
channel.onCordovaConnectionReady.fire();
}
},
function (e) {
// If we can't get the network info we should still tell Cordova
// to fire the deviceready event.
if (me._firstRun) {
me._firstRun = false;
channel.onCordovaConnectionReady.fire();
}
console.log("Error initializing Network Connection: " + e);
});
});
};
/** /**
* Get connection info * Get connection info
@ -6054,12 +5909,48 @@ var NetworkConnection = function () {
* @param {Function} successCallback The function to call when the Connection data is available * @param {Function} successCallback The function to call when the Connection data is available
* @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL) * @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL)
*/ */
NetworkConnection.prototype.getInfo = function (successCallback, errorCallback) { NetworkConnection.prototype.getInfo = function(successCallback, errorCallback) {
// Get info
exec(successCallback, errorCallback, "NetworkStatus", "getConnectionInfo", []); exec(successCallback, errorCallback, "NetworkStatus", "getConnectionInfo", []);
}; };
module.exports = new NetworkConnection(); var me = new NetworkConnection();
var timerId = null;
var timeout = 500;
channel.onCordovaReady.subscribe(function() {
me.getInfo(function(info) {
me.type = info;
if (info === "none") {
// set a timer if still offline at the end of timer send the offline event
timerId = setTimeout(function(){
cordova.fireDocumentEvent("offline");
timerId = null;
}, timeout);
} else {
// If there is a current offline event pending clear it
if (timerId !== null) {
clearTimeout(timerId);
timerId = null;
}
cordova.fireDocumentEvent("online");
}
// should only fire this once
if (channel.onCordovaConnectionReady.state !== 2) {
channel.onCordovaConnectionReady.fire();
}
},
function (e) {
// If we can't get the network info we should still tell Cordova
// to fire the deviceready event.
if (channel.onCordovaConnectionReady.state !== 2) {
channel.onCordovaConnectionReady.fire();
}
console.log("Error initializing Network Connection: " + e);
});
});
module.exports = me;
}); });
@ -6128,7 +6019,8 @@ module.exports = {
// file: lib/common/plugin/requestFileSystem.js // file: lib/common/plugin/requestFileSystem.js
define("cordova/plugin/requestFileSystem", function(require, exports, module) { define("cordova/plugin/requestFileSystem", function(require, exports, module) {
var FileError = require('cordova/plugin/FileError'), var argscheck = require('cordova/argscheck'),
FileError = require('cordova/plugin/FileError'),
FileSystem = require('cordova/plugin/FileSystem'), FileSystem = require('cordova/plugin/FileSystem'),
exec = require('cordova/exec'); exec = require('cordova/exec');
@ -6140,10 +6032,9 @@ var FileError = require('cordova/plugin/FileError'),
* @param errorCallback invoked if error occurs retrieving file system * @param errorCallback invoked if error occurs retrieving file system
*/ */
var requestFileSystem = function(type, size, successCallback, errorCallback) { var requestFileSystem = function(type, size, successCallback, errorCallback) {
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
var fail = function(code) { var fail = function(code) {
if (typeof errorCallback === 'function') { errorCallback && errorCallback(new FileError(code));
errorCallback(new FileError(code));
}
}; };
if (type < 0 || type > 3) { if (type < 0 || type > 3) {
@ -6152,7 +6043,7 @@ var requestFileSystem = function(type, size, successCallback, errorCallback) {
// if successful, return a FileSystem object // if successful, return a FileSystem object
var success = function(file_system) { var success = function(file_system) {
if (file_system) { if (file_system) {
if (typeof successCallback === 'function') { if (successCallback) {
// grab the name and root from the file system object // grab the name and root from the file system object
var result = new FileSystem(file_system.name, file_system.root); var result = new FileSystem(file_system.name, file_system.root);
successCallback(result); successCallback(result);
@ -6174,7 +6065,8 @@ module.exports = requestFileSystem;
// file: lib/common/plugin/resolveLocalFileSystemURI.js // file: lib/common/plugin/resolveLocalFileSystemURI.js
define("cordova/plugin/resolveLocalFileSystemURI", function(require, exports, module) { define("cordova/plugin/resolveLocalFileSystemURI", function(require, exports, module) {
var DirectoryEntry = require('cordova/plugin/DirectoryEntry'), var argscheck = require('cordova/argscheck'),
DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
FileEntry = require('cordova/plugin/FileEntry'), FileEntry = require('cordova/plugin/FileEntry'),
FileError = require('cordova/plugin/FileError'), FileError = require('cordova/plugin/FileError'),
exec = require('cordova/exec'); exec = require('cordova/exec');
@ -6186,11 +6078,10 @@ var DirectoryEntry = require('cordova/plugin/DirectoryEntry'),
* @param errorCallback invoked if error occurs retrieving file system entry * @param errorCallback invoked if error occurs retrieving file system entry
*/ */
module.exports = function(uri, successCallback, errorCallback) { module.exports = function(uri, successCallback, errorCallback) {
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
// error callback // error callback
var fail = function(error) { var fail = function(error) {
if (typeof errorCallback === 'function') { errorCallback && errorCallback(new FileError(error));
errorCallback(new FileError(error));
}
}; };
// sanity check for 'not:valid:filename' // sanity check for 'not:valid:filename'
if(!uri || uri.split(":").length > 2) { if(!uri || uri.split(":").length > 2) {
@ -6203,15 +6094,10 @@ module.exports = function(uri, successCallback, errorCallback) {
var success = function(entry) { var success = function(entry) {
var result; var result;
if (entry) { if (entry) {
if (typeof successCallback === 'function') { if (successCallback) {
// create appropriate Entry object // create appropriate Entry object
result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath) : new FileEntry(entry.name, entry.fullPath); result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath) : new FileEntry(entry.name, entry.fullPath);
try { successCallback(result);
successCallback(result);
}
catch (e) {
console.log('Error invoking callback: ' + e);
}
} }
} }
else { else {
@ -6259,6 +6145,30 @@ utils.defineGetter = function(obj, key, func) {
} }
}; };
utils.arrayIndexOf = function(a, item) {
if (a.indexOf) {
return a.indexOf(item);
}
var len = a.length;
for (var i = 0; i < len; ++i) {
if (a[i] == item) {
return i;
}
}
return -1;
};
/**
* Returns whether the item was found in the array.
*/
utils.arrayRemove = function(a, item) {
var index = utils.arrayIndexOf(a, item);
if (index != -1) {
a.splice(index, 1);
}
return index != -1;
};
/** /**
* Returns an indication of whether the argument is an array or not * Returns an indication of whether the argument is an array or not
*/ */
@ -6454,10 +6364,10 @@ window.cordova = require('cordova');
(function (context) { (function (context) {
// Replace navigator before any modules are required(), to ensure it happens as soon as possible. // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
// We replace it so that properties that can't be clobbered can instead be overridden. // We replace it so that properties that can't be clobbered can instead be overridden.
if (typeof navigator != 'undefined') { if (context.navigator) {
var CordovaNavigator = function () {}; function CordovaNavigator() {}
CordovaNavigator.prototype = navigator; CordovaNavigator.prototype = context.navigator;
navigator = new CordovaNavigator(); context.navigator = new CordovaNavigator();
} }
var channel = require("cordova/channel"), var channel = require("cordova/channel"),
@ -6472,17 +6382,13 @@ window.cordova = require('cordova');
platform = require('cordova/platform'); platform = require('cordova/platform');
// Drop the common globals into the window object, but be nice and don't overwrite anything. // Drop the common globals into the window object, but be nice and don't overwrite anything.
builder.build(base.objects).intoButDoNotClobber(window); builder.buildIntoButDoNotClobber(base.defaults, context);
builder.buildIntoAndMerge(base.merges, context);
builder.buildIntoAndClobber(base.clobbers, context);
// Drop the platform-specific globals into the window object builder.buildIntoButDoNotClobber(platform.defaults, context);
// and clobber any existing object. builder.buildIntoAndMerge(platform.merges, context);
builder.build(platform.objects).intoAndClobber(window); builder.buildIntoAndClobber(platform.clobbers, context);
// Merge the platform-specific overrides/enhancements into
// the window object.
if (typeof platform.merges !== 'undefined') {
builder.build(platform.merges).intoAndMerge(window);
}
// Call the platform-specific initialization // Call the platform-specific initialization
platform.initialize(); platform.initialize();

View File

@ -19,7 +19,7 @@
<html> <html>
<head> <head>
<title></title> <title></title>
<script src="cordova-2.2.0.js"></script> <script src="cordova-2.3.0rc1.js"></script>
</head> </head>
<body> <body>

View File

@ -10,7 +10,7 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=Google Inc.:Google APIs:16 target=Google Inc.:Google APIs:17
apk-configurations= apk-configurations=
renderscript.opt.level=O0 renderscript.opt.level=O0
android.library=true android.library=true

View File

@ -51,6 +51,7 @@
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/> <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
<plugin name="Echo" value="org.apache.cordova.Echo" /> <plugin name="Echo" value="org.apache.cordova.Echo" />
<plugin name="Globalization" value="org.apache.cordova.Globalization"/> <plugin name="Globalization" value="org.apache.cordova.Globalization"/>
<plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser"/>
</plugins> </plugins>
</cordova> </cordova>

View File

@ -19,28 +19,30 @@
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.HashMap; import java.util.HashMap;
/** /**
* This class exposes methods in DroidGap that can be called from JavaScript. * This class exposes methods in DroidGap that can be called from JavaScript.
*/ */
public class App extends Plugin { public class App extends CordovaPlugin {
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
* @param action The action to execute. * @param action The action to execute.
* @param args JSONArry of arguments for the plugin. * @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackContext The callback context from which we were invoked.
* @return A PluginResult object with a status and message. * @return A PluginResult object with a status and message.
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
PluginResult.Status status = PluginResult.Status.OK; PluginResult.Status status = PluginResult.Status.OK;
String result = ""; String result = "";
@ -79,9 +81,11 @@ public class App extends Plugin {
else if (action.equals("exitApp")) { else if (action.equals("exitApp")) {
this.exitApp(); this.exitApp();
} }
return new PluginResult(status, result); callbackContext.sendPluginResult(new PluginResult(status, result));
return true;
} catch (JSONException e) { } catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION); callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
return false;
} }
} }

View File

@ -289,6 +289,17 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// If sending base64 image back // If sending base64 image back
if (destType == DATA_URL) { if (destType == DATA_URL) {
bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString())); bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString()));
if (bitmap == null) {
// Try to get the bitmap from intent.
bitmap = (Bitmap)intent.getExtras().get("data");
}
// Double-check the bitmap.
if (bitmap == null) {
Log.d(LOG_TAG, "I either have a null image path or bitmap");
this.failPicture("Unable to create bitmap!");
return;
}
if (rotate != 0 && this.correctOrientation) { if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif); bitmap = getRotatedBitmap(rotate, bitmap, exif);
@ -567,6 +578,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
options.inJustDecodeBounds = false; options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight); options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options); Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options);
if (unscaledBitmap == null) {
return null;
}
return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true); return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true);
} }

View File

@ -127,7 +127,7 @@ public class Capture extends CordovaPlugin {
// If the mimeType isn't set the rest will fail // If the mimeType isn't set the rest will fail
// so let's see if we can determine it. // so let's see if we can determine it.
if (mimeType == null || mimeType.equals("")) { if (mimeType == null || mimeType.equals("") || "null".equals(mimeType)) {
mimeType = FileUtils.getMimeType(filePath); mimeType = FileUtils.getMimeType(filePath);
} }
Log.d(LOG_TAG, "Mime type = " + mimeType); Log.d(LOG_TAG, "Mime type = " + mimeType);

View File

@ -1579,7 +1579,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
Uri uri = Uri.parse(path); Uri uri = Uri.parse(path);
return mApp.getActivity().getContentResolver().openInputStream(uri); return mApp.getActivity().getContentResolver().openInputStream(uri);
} }
if (path.startsWith("http:") || path.startsWith("file:")) { if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
URL url = new URL(path); URL url = new URL(path);
return url.openStream(); return url.openStream();
} }

View File

@ -20,6 +20,8 @@
package org.apache.cordova; package org.apache.cordova;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -98,8 +100,8 @@ public class CordovaWebView extends WebView {
private long lastMenuEventTime = 0; private long lastMenuEventTime = 0;
NativeToJsMessageQueue jsMessageQueue; NativeToJsMessageQueue jsMessageQueue;
ExposedJsApi exposedJsApi; ExposedJsApi exposedJsApi;
/** custom view created by the browser (a video player for example) */ /** custom view created by the browser (a video player for example) */
private View mCustomView; private View mCustomView;
@ -200,8 +202,8 @@ public class CordovaWebView extends WebView {
* @param defStyle * @param defStyle
* @param privateBrowsing * @param privateBrowsing
*/ */
@TargetApi(11) @TargetApi(11)
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) { public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context, attrs, defStyle, privateBrowsing); super(context, attrs, defStyle, privateBrowsing);
if (CordovaInterface.class.isInstance(context)) if (CordovaInterface.class.isInstance(context))
{ {
@ -244,15 +246,28 @@ public class CordovaWebView extends WebView {
settings.setJavaScriptEnabled(true); settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
//Set the nav dump for HTC 2.x devices (disabling for ICS/Jellybean)
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
settings.setNavDump(true);
// Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
try {
Method gingerbread_getMethod = WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
{
gingerbread_getMethod.invoke(settings, true);
}
} catch (NoSuchMethodException e) {
Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
} catch (IllegalArgumentException e) {
Log.d(TAG, "Doing the NavDump failed with bad arguments");
} catch (IllegalAccessException e) {
Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
} catch (InvocationTargetException e) {
Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
}
// Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
// while we do this // while we do this
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
Level16Apis.enableUniversalAccess(settings); Level16Apis.enableUniversalAccess(settings);
// Enable database // Enable database
settings.setDatabaseEnabled(true); settings.setDatabaseEnabled(true);
String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
@ -288,17 +303,19 @@ public class CordovaWebView extends WebView {
} }
private void updateUserAgentString() { private void updateUserAgentString() {
this.getSettings().getUserAgentString(); this.getSettings().getUserAgentString();
} }
private void exposeJsInterface() { private void exposeJsInterface() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) { int SDK_INT = Build.VERSION.SDK_INT;
boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old."); Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically. // Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just // This isn't hard to work-around on the JS side, but it's easier to just
// use the prompt bridge instead. // use the prompt bridge instead.
return; return;
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) { } else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
// addJavascriptInterface crashes on the 2.3 emulator. // addJavascriptInterface crashes on the 2.3 emulator.
Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator"); Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
return; return;
@ -610,7 +627,7 @@ public class CordovaWebView extends WebView {
// Check webview first to see if there is a history // Check webview first to see if there is a history
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior) // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
if (super.canGoBack()) { if (super.canGoBack()) {
printBackForwardList(); printBackForwardList();
super.goBack(); super.goBack();
return true; return true;
@ -841,27 +858,27 @@ public class CordovaWebView extends WebView {
// If back key // If back key
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
// A custom view is currently displayed (e.g. playing a video) // A custom view is currently displayed (e.g. playing a video)
if(mCustomView != null) { if(mCustomView != null) {
this.hideCustomView(); this.hideCustomView();
} else { } else {
// The webview is currently displayed // The webview is currently displayed
// If back key is bound, then send event to JavaScript // If back key is bound, then send event to JavaScript
if (this.bound) { if (this.bound) {
this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');"); this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
return true; return true;
} else { } else {
// If not bound // If not bound
// Go to previous page in webview if it is possible to go back // Go to previous page in webview if it is possible to go back
if (this.backHistory()) { if (this.backHistory()) {
return true; return true;
} }
// If not, then invoke default behaviour // If not, then invoke default behaviour
else { else {
//this.activityState = ACTIVITY_EXITING; //this.activityState = ACTIVITY_EXITING;
return false; return false;
} }
} }
} }
} }
// Legacy // Legacy
else if (keyCode == KeyEvent.KEYCODE_MENU) { else if (keyCode == KeyEvent.KEYCODE_MENU) {
@ -1003,14 +1020,14 @@ public class CordovaWebView extends WebView {
} }
public void printBackForwardList() { public void printBackForwardList() {
WebBackForwardList currentList = this.copyBackForwardList(); WebBackForwardList currentList = this.copyBackForwardList();
int currentSize = currentList.getSize(); int currentSize = currentList.getSize();
for(int i = 0; i < currentSize; ++i) for(int i = 0; i < currentSize; ++i)
{ {
WebHistoryItem item = currentList.getItemAtIndex(i); WebHistoryItem item = currentList.getItemAtIndex(i);
String url = item.getUrl(); String url = item.getUrl();
LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url ); LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url );
} }
} }
@ -1027,8 +1044,8 @@ public class CordovaWebView extends WebView {
} }
public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) { public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "showing Custom View"); Log.d(TAG, "showing Custom View");
// if a view already exists then immediately terminate the new one // if a view already exists then immediately terminate the new one
if (mCustomView != null) { if (mCustomView != null) {
callback.onCustomViewHidden(); callback.onCustomViewHidden();
@ -1036,57 +1053,57 @@ public class CordovaWebView extends WebView {
} }
// Store the view and its callback for later (to kill it properly) // Store the view and its callback for later (to kill it properly)
mCustomView = view; mCustomView = view;
mCustomViewCallback = callback; mCustomViewCallback = callback;
// Add the custom view to its container. // Add the custom view to its container.
ViewGroup parent = (ViewGroup) this.getParent(); ViewGroup parent = (ViewGroup) this.getParent();
parent.addView(view, COVER_SCREEN_GRAVITY_CENTER); parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
// Hide the content view. // Hide the content view.
this.setVisibility(View.GONE); this.setVisibility(View.GONE);
// Finally show the custom view container. // Finally show the custom view container.
parent.setVisibility(View.VISIBLE); parent.setVisibility(View.VISIBLE);
parent.bringToFront(); parent.bringToFront();
} }
public void hideCustomView() { public void hideCustomView() {
// This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
Log.d(TAG, "Hidding Custom View"); Log.d(TAG, "Hidding Custom View");
if (mCustomView == null) return; if (mCustomView == null) return;
// Hide the custom view. // Hide the custom view.
mCustomView.setVisibility(View.GONE); mCustomView.setVisibility(View.GONE);
// Remove the custom view from its container. // Remove the custom view from its container.
ViewGroup parent = (ViewGroup) this.getParent(); ViewGroup parent = (ViewGroup) this.getParent();
parent.removeView(mCustomView); parent.removeView(mCustomView);
mCustomView = null; mCustomView = null;
mCustomViewCallback.onCustomViewHidden(); mCustomViewCallback.onCustomViewHidden();
// Show the content view. // Show the content view.
this.setVisibility(View.VISIBLE); this.setVisibility(View.VISIBLE);
} }
/** /**
* if the video overlay is showing then we need to know * if the video overlay is showing then we need to know
* as it effects back button handling * as it effects back button handling
* *
* @return * @return
*/ */
public boolean isCustomViewShowing() { public boolean isCustomViewShowing() {
return mCustomView != null; return mCustomView != null;
} }
public WebBackForwardList restoreState(Bundle savedInstanceState) public WebBackForwardList restoreState(Bundle savedInstanceState)
{ {
WebBackForwardList myList = super.restoreState(savedInstanceState); WebBackForwardList myList = super.restoreState(savedInstanceState);
Log.d(TAG, "WebView restoration crew now restoring!"); Log.d(TAG, "WebView restoration crew now restoring!");
//Initialize the plugin manager once more //Initialize the plugin manager once more
this.pluginManager.init(); this.pluginManager.init();
return myList; return myList;
} }
public void storeResult(int requestCode, int resultCode, Intent intent) { public void storeResult(int requestCode, int resultCode, Intent intent) {
mResult = new ActivityResult(requestCode, resultCode, intent); mResult = new ActivityResult(requestCode, resultCode, intent);

View File

@ -39,7 +39,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin { public class Device extends CordovaPlugin {
public static final String TAG = "Device"; public static final String TAG = "Device";
public static String cordovaVersion = "2.2.0"; // Cordova version public static String cordovaVersion = "2.3.0rc1"; // Cordova version
public static String platform = "Android"; // Device OS public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID public static String uuid; // Device UUID
@ -80,9 +80,7 @@ public class Device extends CordovaPlugin {
r.put("platform", Device.platform); r.put("platform", Device.platform);
r.put("name", this.getProductName()); r.put("name", this.getProductName());
r.put("cordova", Device.cordovaVersion); r.put("cordova", Device.cordovaVersion);
//JSONObject pg = new JSONObject(); r.put("model", this.getProductName());
//pg.put("version", Device.CordovaVersion);
//r.put("cordova", pg);
callbackContext.success(r); callbackContext.success(r);
} }
else { else {

View File

@ -40,7 +40,6 @@ import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import android.view.Display; import android.view.Display;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@ -156,11 +155,6 @@ public class DroidGap extends Activity implements CordovaInterface {
private static int ACTIVITY_EXITING = 2; private static int ACTIVITY_EXITING = 2;
private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down
// The base of the initial URL for our app.
// Does not include file name. Ends with /
// ie http://server/path/
String baseUrl = null;
// Plugin to call when activity result is received // Plugin to call when activity result is received
protected CordovaPlugin activityResultCallback = null; protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning; protected boolean activityResultKeepRunning;
@ -859,7 +853,7 @@ public class DroidGap extends Activity implements CordovaInterface {
// If errorUrl specified, then load it // If errorUrl specified, then load it
final String errorUrl = me.getStringProperty("errorUrl", null); final String errorUrl = me.getStringProperty("errorUrl", null);
if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) { if ((errorUrl != null) && (errorUrl.startsWith("file://") || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
// Load URL on UI thread // Load URL on UI thread
me.runOnUiThread(new Runnable() { me.runOnUiThread(new Runnable() {

View File

@ -18,6 +18,7 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import android.webkit.JavascriptInterface;
import org.apache.cordova.api.PluginManager; import org.apache.cordova.api.PluginManager;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
import org.json.JSONException; import org.json.JSONException;
@ -37,6 +38,7 @@ import org.json.JSONException;
this.jsMessageQueue = jsMessageQueue; this.jsMessageQueue = jsMessageQueue;
} }
@JavascriptInterface
public String exec(String service, String action, String callbackId, String arguments) throws JSONException { public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
jsMessageQueue.setPaused(true); jsMessageQueue.setPaused(true);
try { try {
@ -51,10 +53,12 @@ import org.json.JSONException;
} }
} }
@JavascriptInterface
public void setNativeToJsBridgeMode(int value) { public void setNativeToJsBridgeMode(int value) {
jsMessageQueue.setBridgeMode(value); jsMessageQueue.setBridgeMode(value);
} }
@JavascriptInterface
public String retrieveJsMessages() { public String retrieveJsMessages() {
return jsMessageQueue.popAndEncode(); return jsMessageQueue.popAndEncode();
} }

View File

@ -984,8 +984,16 @@ public class FileUtils extends CordovaPlugin {
* @return a mime type * @return a mime type
*/ */
public static String getMimeType(String filename) { public static String getMimeType(String filename) {
// Stupid bug in getFileExtensionFromUrl when the file name has a space
// So we need to replace the space with a url encoded %20
String url = filename.replace(" ", "%20");
MimeTypeMap map = MimeTypeMap.getSingleton(); MimeTypeMap map = MimeTypeMap.getSingleton();
return map.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(filename)); String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension.toLowerCase().equals("3ga")) {
return "audio/3gpp";
} else {
return map.getMimeTypeFromExtension(extension);
}
} }
/** /**
@ -1069,16 +1077,18 @@ public class FileUtils extends CordovaPlugin {
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) { protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) {
String uri = contentUri.toString(); final String scheme = contentUri.getScheme();
if (uri.startsWith("content:")) {
if (scheme.compareTo("content") == 0) {
String[] proj = { _DATA }; String[] proj = { _DATA };
Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null); Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA); int column_index = cursor.getColumnIndexOrThrow(_DATA);
cursor.moveToFirst(); cursor.moveToFirst();
return cursor.getString(column_index); return cursor.getString(column_index);
} else if (scheme.compareTo("file") == 0) {
return contentUri.getPath();
} else { } else {
return uri; return contentUri.toString();
} }
} }
} }

View File

@ -0,0 +1,513 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import java.io.InputStream;
import java.util.HashMap;
import java.util.StringTokenizer;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
public class InAppBrowser extends CordovaPlugin {
private static final String NULL = "null";
protected static final String LOG_TAG = "InAppBrowser";
private static final String SELF = "_self";
private static final String SYSTEM = "_system";
private static final String BLANK = "_blank";
private static final String LOCATION = "location";
private static int CLOSE_EVENT = 0;
private static int LOCATION_CHANGED_EVENT = 1;
private String browserCallbackId = null;
private Dialog dialog;
private WebView inAppWebView;
private EditText edittext;
private boolean showLocationBar = true;
private CallbackContext callbackContext;
/**
* Executes the request and returns PluginResult.
*
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message.
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
this.callbackContext = callbackContext;
try {
if (action.equals("open")) {
String url = args.getString(0);
String target = args.optString(1);
if (target == null || target.equals("") || target.equals(NULL)) {
target = SELF;
}
HashMap<String, Boolean> features = parseFeature(args.optString(2));
Log.d(LOG_TAG, "target = " + target);
url = updateUrl(url);
// SELF
if (SELF.equals(target)) {
Log.d(LOG_TAG, "in self");
// load in webview
if (url.startsWith("file://") || url.startsWith("javascript:")
|| this.webView.isUrlWhiteListed(url)) {
this.webView.loadUrl(url);
}
// load in InAppBrowser
else {
result = this.showWebPage(url, features);
}
}
// SYSTEM
else if (SYSTEM.equals(target)) {
Log.d(LOG_TAG, "in system");
result = this.openExternal(url);
}
// BLANK - or anything else
else {
Log.d(LOG_TAG, "in blank");
result = this.showWebPage(url, features);
}
}
else if (action.equals("close")) {
closeDialog();
JSONObject obj = new JSONObject();
obj.put("type", CLOSE_EVENT);
PluginResult pluginResult = new PluginResult(status, obj);
pluginResult.setKeepCallback(false);
this.callbackContext.sendPluginResult(pluginResult);
}
else {
status = PluginResult.Status.INVALID_ACTION;
}
this.callbackContext.sendPluginResult(new PluginResult(status, result));
} catch (JSONException e) {
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
}
return true;
}
/**
* Put the list of features into a hash map
*
* @param optString
* @return
*/
private HashMap<String, Boolean> parseFeature(String optString) {
if (optString.equals(NULL)) {
return null;
} else {
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
StringTokenizer features = new StringTokenizer(optString, ",");
StringTokenizer option;
while(features.hasMoreElements()) {
option = new StringTokenizer(features.nextToken(), "=");
if (option.hasMoreElements()) {
String key = option.nextToken();
Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
map.put(key, value);
}
}
return map;
}
}
/**
* Convert relative URL to full path
*
* @param url
* @return
*/
private String updateUrl(String url) {
Uri newUrl = Uri.parse(url);
if (newUrl.isRelative()) {
url = this.webView.getUrl().substring(0, this.webView.getUrl().lastIndexOf("/")+1) + url;
}
return url;
}
/**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param usePhoneGap Load url in PhoneGap webview
* @return "" if ok, or error message.
*/
public String openExternal(String url) {
try {
Intent intent = null;
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
this.cordova.getActivity().startActivity(intent);
return "";
} catch (android.content.ActivityNotFoundException e) {
Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
return e.toString();
}
}
/**
* Closes the dialog
*/
private void closeDialog() {
// TODO: fire 'exit' event
this.webView.sendJavascript("cordova.fireWindowEvent('exit');");
if (dialog != null) {
dialog.dismiss();
}
}
/**
* Checks to see if it is possible to go back one page in history, then does so.
*/
private void goBack() {
if (this.inAppWebView.canGoBack()) {
this.inAppWebView.goBack();
}
}
/**
* Checks to see if it is possible to go forward one page in history, then does so.
*/
private void goForward() {
if (this.inAppWebView.canGoForward()) {
this.inAppWebView.goForward();
}
}
/**
* Navigate to the new page
*
* @param url to load
*/
private void navigate(String url) {
InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
if (!url.startsWith("http") && !url.startsWith("file:")) {
this.inAppWebView.loadUrl("http://" + url);
} else {
this.inAppWebView.loadUrl(url);
}
this.inAppWebView.requestFocus();
}
/**
* Should we show the location bar?
*
* @return boolean
*/
private boolean getShowLocationBar() {
return this.showLocationBar;
}
/**
* Display a new browser with the specified URL.
*
* @param url The url to load.
* @param jsonObject
*/
public String showWebPage(final String url, HashMap<String, Boolean> features) {
// Determine if we should hide the location bar.
showLocationBar = true;
if (features != null) {
showLocationBar = features.get(LOCATION).booleanValue();
}
final CordovaWebView thatWebView = this.webView;
// Create dialog in new thread
Runnable runnable = new Runnable() {
/**
* Convert our DIP units to Pixels
*
* @return int
*/
private int dpToPixels(int dipValue) {
int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
(float) dipValue,
cordova.getActivity().getResources().getDisplayMetrics()
);
return value;
}
public void run() {
// Let's create the main dialog
dialog = new Dialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
try {
JSONObject obj = new JSONObject();
obj.put("type", CLOSE_EVENT);
sendUpdate(obj, false);
} catch (JSONException e) {
Log.d(LOG_TAG, "Should never happen");
}
}
});
// Main container layout
LinearLayout main = new LinearLayout(cordova.getActivity());
main.setOrientation(LinearLayout.VERTICAL);
// Toolbar layout
RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, this.dpToPixels(44)));
toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
toolbar.setHorizontalGravity(Gravity.LEFT);
toolbar.setVerticalGravity(Gravity.TOP);
// Action Button Container layout
RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
actionButtonContainer.setId(1);
// Back button
Button back = new Button(cordova.getActivity());
RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
back.setLayoutParams(backLayoutParams);
back.setContentDescription("Back Button");
back.setId(2);
back.setText("<");
back.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goBack();
}
});
// Forward button
Button forward = new Button(cordova.getActivity());
RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
forward.setLayoutParams(forwardLayoutParams);
forward.setContentDescription("Forward Button");
forward.setId(3);
forward.setText(">");
forward.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goForward();
}
});
// Edit Text Box
edittext = new EditText(cordova.getActivity());
RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
edittext.setLayoutParams(textLayoutParams);
edittext.setId(4);
edittext.setSingleLine(true);
edittext.setText(url);
edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
edittext.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
navigate(edittext.getText().toString());
return true;
}
return false;
}
});
// Close button
Button close = new Button(cordova.getActivity());
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
close.setLayoutParams(closeLayoutParams);
forward.setContentDescription("Close Button");
close.setId(5);
close.setText("Done");
close.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
closeDialog();
}
});
// WebView
inAppWebView = new WebView(cordova.getActivity());
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
inAppWebView.setWebChromeClient(new WebChromeClient());
WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
inAppWebView.setWebViewClient(client);
WebSettings settings = inAppWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setBuiltInZoomControls(true);
settings.setPluginsEnabled(true);
settings.setDomStorageEnabled(true);
inAppWebView.loadUrl(url);
inAppWebView.setId(6);
inAppWebView.getSettings().setLoadWithOverviewMode(true);
inAppWebView.getSettings().setUseWideViewPort(true);
inAppWebView.requestFocus();
inAppWebView.requestFocusFromTouch();
// Add the back and forward buttons to our action button container layout
actionButtonContainer.addView(back);
actionButtonContainer.addView(forward);
// Add the views to our toolbar
toolbar.addView(actionButtonContainer);
toolbar.addView(edittext);
toolbar.addView(close);
// Don't add the toolbar if its been disabled
if (getShowLocationBar()) {
// Add our toolbar to our main view/layout
main.addView(toolbar);
}
// Add our webview to our main view/layout
main.addView(inAppWebView);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.FILL_PARENT;
lp.height = WindowManager.LayoutParams.FILL_PARENT;
dialog.setContentView(main);
dialog.show();
dialog.getWindow().setAttributes(lp);
}
private Bitmap loadDrawable(String filename) throws java.io.IOException {
InputStream input = cordova.getActivity().getAssets().open(filename);
return BitmapFactory.decodeStream(input);
}
};
this.cordova.getActivity().runOnUiThread(runnable);
return "";
}
/**
* Create a new plugin result and send it back to JavaScript
*
* @param obj a JSONObject contain event payload information
*/
private void sendUpdate(JSONObject obj, boolean keepCallback) {
if (this.browserCallbackId != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
result.setKeepCallback(keepCallback);
this.callbackContext.sendPluginResult(result);
}
}
/**
* The webview client receives notifications about appView
*/
public class InAppBrowserClient extends WebViewClient {
EditText edittext;
CordovaWebView webView;
/**
* Constructor.
*
* @param mContext
* @param edittext
*/
public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
this.webView = webView;
this.edittext = mEditText;
}
/**
* Notify the host application that a page has started loading.
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
String newloc;
if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
newloc = url;
} else {
newloc = "http://" + url;
}
if (!newloc.equals(edittext.getText().toString())) {
edittext.setText(newloc);
}
// TODO: Fire 'loadstart' event only on the InAppBrowser object
this.webView.sendJavascript("cordova.fireWindowEvent('loadstart', '" + url + "');");
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// TODO: Fire 'loadstop' event only on the InAppBrowser object
this.webView.sendJavascript("cordova.fireWindowEvent('loadstop', '" + url + "');");
}
}
}

View File

@ -74,6 +74,7 @@ public class NetworkManager extends CordovaPlugin {
ConnectivityManager sockMan; ConnectivityManager sockMan;
BroadcastReceiver receiver; BroadcastReceiver receiver;
private String lastStatus = "";
/** /**
* Constructor. * Constructor.
@ -99,12 +100,11 @@ public class NetworkManager extends CordovaPlugin {
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
if (this.receiver == null) { if (this.receiver == null) {
this.receiver = new BroadcastReceiver() { this.receiver = new BroadcastReceiver() {
@SuppressWarnings("deprecation")
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
// (The null check is for the ARM Emulator, please use Intel Emulator for better results) // (The null check is for the ARM Emulator, please use Intel Emulator for better results)
if(NetworkManager.this.webView != null) if(NetworkManager.this.webView != null)
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO)); updateConnectionInfo(sockMan.getActiveNetworkInfo());
} }
}; };
cordova.getActivity().registerReceiver(this.receiver, intentFilter); cordova.getActivity().registerReceiver(this.receiver, intentFilter);
@ -147,13 +147,6 @@ public class NetworkManager extends CordovaPlugin {
} }
} }
/**
* Stop the network receiver on navigation.
*/
public void onReset() {
this.onDestroy();
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -166,7 +159,14 @@ public class NetworkManager extends CordovaPlugin {
*/ */
private void updateConnectionInfo(NetworkInfo info) { private void updateConnectionInfo(NetworkInfo info) {
// send update to javascript "navigator.network.connection" // send update to javascript "navigator.network.connection"
sendUpdate(this.getConnectionInfo(info)); // Jellybean sends its own info
String thisStatus = this.getConnectionInfo(info);
if(!thisStatus.equals(lastStatus))
{
sendUpdate(thisStatus);
lastStatus = thisStatus;
}
} }
/** /**
@ -186,6 +186,7 @@ public class NetworkManager extends CordovaPlugin {
type = getType(info); type = getType(info);
} }
} }
Log.d("CordovaNetworkManager", "Connection Type: " + type);
return type; return type;
} }
@ -200,7 +201,6 @@ public class NetworkManager extends CordovaPlugin {
result.setKeepCallback(true); result.setKeepCallback(true);
connectionCallbackContext.sendPluginResult(result); connectionCallbackContext.sendPluginResult(result);
} }
webView.postMessage("networkconnection", type); webView.postMessage("networkconnection", type);
} }

View File

@ -255,5 +255,15 @@
<category android:name="android.intent.category.SAMPLE_CODE" /> <category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".actions.backbuttonmultipage" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
</application> </application>
</manifest> </manifest>

View File

@ -26,6 +26,7 @@ import org.apache.cordova.test.actions.backbuttonmultipage;
import android.test.ActivityInstrumentationTestCase2; import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -97,6 +98,54 @@ public class BackButtonMultiPageTest extends ActivityInstrumentationTestCase2<ba
assertTrue(didGoBack); assertTrue(didGoBack);
} }
public void testViaBackButtonOnView() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(testView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
public void testViaBackButtonOnLayout() {
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
sleep();
String url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
testView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(containerView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("sample2.html"));
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
sleep();
url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
private void sleep() { private void sleep() {
try { try {
Thread.sleep(TIMEOUT); Thread.sleep(TIMEOUT);

View File

@ -49,6 +49,8 @@ public class CordovaTest extends
} }
public void testForCordovaView() { public void testForCordovaView() {
//Sleep for no reason!!!!
sleep();
String className = testView.getClass().getSimpleName(); String className = testView.getClass().getSimpleName();
assertTrue(className.equals("CordovaWebView")); assertTrue(className.equals("CordovaWebView"));
} }

View File

@ -25,6 +25,7 @@ import java.util.concurrent.Executors;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.CordovaInterface; import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.CordovaPlugin; import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.test.R; import org.apache.cordova.test.R;
import org.apache.cordova.test.R.id; import org.apache.cordova.test.R.id;
import org.apache.cordova.test.R.layout; import org.apache.cordova.test.R.layout;
@ -52,14 +53,6 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
} }
public void onDestroy()
{
super.onDestroy();
if (cordovaWebView.pluginManager != null) {
cordovaWebView.pluginManager.onDestroy();
}
}
public Context getContext() { public Context getContext() {
return this; return this;
} }
@ -95,4 +88,17 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
// TODO Auto-generated method stub // TODO Auto-generated method stub
return threadPool; return threadPool;
} }
@Override
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
super.onDestroy();
if (cordovaWebView != null) {
// Send destroy event to JavaScript
cordovaWebView.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
cordovaWebView.handleDestroy();
}
}
} }