Compare commits

...

43 Commits

Author SHA1 Message Date
Joe Bowser
fb1455a17b Preparing to tag 2.5.0 2013-02-26 13:49:47 -08:00
Joe Bowser
5462eddfdb Updating the JS for 2.5.0rc1 2013-02-20 13:52:29 -08:00
Joe Bowser
fef51f12c6 Apparently the JS was wrong when tagging 2013-02-20 13:06:13 -08:00
Joe Bowser
5cd17730b1 Tagging 2.5.0rc1. Updating files 2013-02-19 11:53:36 -08:00
mbillau
cb192056f8 CB-2458: gracefully exit with back button
If users do extra initialization, we can get NPEs when hitting the back
button before loadUrl() has been called.
-Null fenced code in startOfHistory() that gave us an NPE when hitting
Back button with useBrowserHistory=true
-Call finish() in Back button code when no history since with
useBrowserHistory=true it would just hang while the app inits
-Call loadUrlIntoView() first in handleDestory() since with
useBrowserHistory=false, the default behavior would try to use the baseUrl
which is null
2013-02-18 16:42:14 -05:00
Joe Bowser
892f96e305 CB-2282: Turning on AppCache 2013-02-18 11:37:28 -08:00
Joe Bowser
13ef58a5bb Updated XML for the test project 2013-02-18 11:26:40 -08:00
Joe Bowser
a45d5a98dd CB-1605: Going through Eclipse warnings, removing the unused imports 2013-02-15 15:46:36 -08:00
Joe Bowser
a31714f8a4 CB-2447: This is a non-trivial task. Migrated test plugin to modern plugin API. 2013-02-15 14:25:56 -08:00
Joe Bowser
23d2a806f0 Merge branch 'CB-2447' of git://github.com/jamesjong/cordova-android 2013-02-15 14:02:23 -08:00
Joe Bowser
c20b2330ab CB-2446: Ugly, but workable fix 2013-02-15 13:57:34 -08:00
Fil Maj
8613551aec minor readme stuff 2013-02-15 13:18:03 -08:00
Fil Maj
2ab01dadc0 Adding link to cordova.io in readme 2013-02-15 13:12:19 -08:00
James Jong
790636c8cd CB-2447: Remove use of deprecate org.apache.cordova.api.Plugin 2013-02-15 13:18:58 -05:00
Andrew Grieve
23938830f7 [CB-2213] Add NATIVE_URI to the quick-return logic. 2013-02-14 10:50:37 -05:00
Benn Mapes
674b87057a [CB-2297] Fix for geolocaion database error 2013-02-12 14:23:01 -08:00
Richard Kolkovich
83d9248ec8 Update framework/src/org/apache/cordova/ContactAccessorSdk5.java
`Im.PROTOCOL` is a String, not an int. Treat it as such to prevent an Exception being thrown when parsing `null`.
2013-02-12 16:18:50 -05:00
Joe Bowser
f9d27e4a67 CB-2408: There should be a check for the browser history, but the logic intentionally doesn't match 2013-02-12 11:16:01 -08:00
patrick kettner
2683803ef3 Add check for build targets in create script
I installed the android sdk via homebrew, which does not install any build targets by default.

That resulted in the create throwing the following somewhat cryptic error.

An unexpected error occurred: "$ANDROID_BIN" create project --target $TARGET --path "$PROJECT_PATH" --package $PACKAGE --activity $ACTIVITY >&/dev/null exited with 1

This just adds a check that the variables that are set to the values of the build targets are properly set, and exit if they are not.
2013-02-12 11:07:51 -05:00
Andrew Grieve
dd86d7a5ed [CB-2095] Delete file on FileTransfer.download fail 2013-02-12 10:55:33 -05:00
Max Woghiren
1246a81d39 [CB-2213] Added NATIVE_URI support.
This is mostly the same as FILE_URI on Android.

Also replaced calls to `stripFileProtocol` with the more general-purpose `getRealPathFromURI`.  This helps support some operations on content URIs.
2013-02-11 22:45:14 -05:00
Andrew Grieve
8ab7278db2 Code clean-up of FileTransfer
- Fix warnings about toLowerCase()
- Don't assume connections are HTTP (fails for file://)
- Use StringBuilder
- Remove no-ops of disconnect() & keep-alive
2013-02-11 22:35:17 -05:00
Joe Bowser
db099e7722 Preparing for 2.4.0 2013-02-04 11:12:52 -08:00
Joe Bowser
fcc01bc37e Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android 2013-01-31 10:45:02 -08:00
Joe Bowser
a18dacf5f2 CB-2296 - Adding the screenshot configuration 2013-01-31 10:44:46 -08:00
Anis Kadri
77f9cae50b CB-1961 update to create script for android/windows 2013-01-30 14:57:49 -08:00
Joe Bowser
3610bbf21b CB-2296: Adding deprecation notices for removing the setProperties methods 2013-01-30 11:31:59 -08:00
Joe Bowser
d5e3be9a55 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android 2013-01-30 11:13:28 -08:00
Joe Bowser
80b369d6d5 CB-2296: Added parsing for Integer and Boolean parameters in config.xml 2013-01-30 11:13:07 -08:00
Andrew Grieve
d29eb84010 Tagging 2.4.0rc2 2013-01-30 09:51:40 -05:00
Joe Bowser
381ce535bf Merge branch 'puritytool' 2013-01-29 15:20:21 -08:00
Andrew Grieve
2e20bb0639 [CB-2293] Fix typo bufferSize->bytesRead.
Also adds a log statement to print out amount uploaded when an
IOException is thrown.
2013-01-29 13:47:15 -05:00
Joe Bowser
56cd24797e Fix for CB-2284. 401s are appearing when we hit them 2013-01-25 16:39:02 -08:00
Joe Bowser
431ca99c23 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android 2013-01-25 14:41:26 -08:00
Joe Bowser
6ced2ff293 CB-2292: Added a check for width and height. You can't scale nothing because you can't divide by zero. 2013-01-25 14:41:14 -08:00
Joe Bowser
31055bb303 Update to purity, adding better touch support 2013-01-25 14:39:44 -08:00
Fil Maj
24a53e39dd hey new line 2013-01-23 18:31:30 -08:00
Fil Maj
2ab113b695 Removing notice about incubation in the readme. 2013-01-23 12:21:49 -08:00
Fil Maj
9a0481a750 tweaking readme 2013-01-23 12:17:42 -08:00
Fil Maj
09035eb4c4 Setting template AndroidManifest values for version to 1.0 and code to 1. 2013-01-23 12:13:07 -08:00
Joe Bowser
1adf268e71 Updates to tests, including the use of Purity 2013-01-22 15:18:21 -08:00
Joe Bowser
23f57ad5a7 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android into puritytool 2013-01-21 14:59:04 -08:00
Joe Bowser
66f15fdd37 Adding purity to the test suite. Purity is a test class that may be renamed later 2013-01-18 15:00:02 -08:00
35 changed files with 1387 additions and 1031 deletions

View File

@@ -1,16 +1,12 @@
Cordova Android
===
Cordova Android is an Android application library that allows for Cordova based projects to be built for the Android Platform. Cordova based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
Cordova Android is an Android application library that allows for Cordova-based
projects to be built for the Android Platform. Cordova based applications are,
at the core, applications written with web technology: HTML, CSS and JavaScript.
[Apache Cordova](http://cordova.io) is a project at The Apache Software Foundation (ASF).
Apache Cordova is an effort undergoing incubation at The Apache
Software Foundation (ASF), sponsored by the Apache Incubator project.
Incubation is required of all newly accepted projects until a further
review indicates that the infrastructure, communications, and decision
making process have stabilized in a manner consistent with other
successful ASF projects. While incubation status is not necessarily
a reflection of the completeness or stability of the code, it does
indicate that the project has yet to be fully endorsed by the ASF.
Requires
---
@@ -27,7 +23,7 @@ Test Requirements
Building
---
To create your cordova.jar, copy the commons codec:
To create your `cordova.jar` file, copy the commons codec:
mv commons-codec-1.7.jar framework/libs

View File

@@ -1 +1 @@
2.4.0rc1
2.5.0

View File

@@ -98,6 +98,13 @@ MANIFEST_PATH="$PROJECT_PATH"/AndroidManifest.xml
TARGET=$("$ANDROID_BIN" list targets | grep id: | tail -1 | cut -f 2 -d ' ' )
API_LEVEL=$("$ANDROID_BIN" list target | grep "API level:" | tail -n 1 | cut -f 2 -d ':' | tr -d ' ')
# check that build targets exist
if [ -z "$TARGET" ] || [ -z "$API_LEVEL" ]
then
echo "No Android Targets are installed. Please install at least one via the android SDK"
exit 1
fi
# if this a distribution release no need to build a jar
if [ ! -e "$BUILD_PATH"/cordova-$VERSION.jar ] && [ -d "$BUILD_PATH"/framework ]
then

View File

@@ -33,12 +33,22 @@ function read(filename) {
f.Close();
return s;
}
function checkTargets(targets) {
if(!targets) {
WScript.Echo("You do not have any android targets setup. Please create at least one target with the `android` command");
WScript.Quit(69);
}
}
function setTarget() {
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s\d+/g);
checkTargets(targets);
return targets[targets.length - 1].replace(/id: /, ""); // TODO: give users the option to set their target
}
function setApiLevel() {
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/API level:\s\d+/g);
checkTargets(targets);
return targets[targets.length - 1].replace(/API level: /, "");
}
function write(filename, contents) {

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="__PACKAGE__" android:versionName="1.1" android:versionCode="5" android:hardwareAccelerated="true">
package="__PACKAGE__" android:versionName="1.0" android:versionCode="1" android:hardwareAccelerated="true">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

View File

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

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova" android:versionName="1.1" android:versionCode="5">
package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

View File

@@ -1,6 +1,8 @@
// commit 71223711fb1591b1255d871140d959fd9095f0c3
// Platform: android
// File generated at :: Mon Jan 21 2013 13:45:08 GMT-0800 (PST)
// commit f50d20a87431c79a54572263729461883f611a53
// File generated at :: Tue Feb 26 2013 13:37:51 GMT-0800 (PST)
/*
Licensed to the Apache Software Foundation (ASF) under one
@@ -397,6 +399,7 @@ function each(objects, func, context) {
}
function clobber(obj, key, value) {
exports.replaceHookForTesting(obj, key);
obj[key] = value;
// Getters can only be overridden by getters.
if (obj[key] !== value) {
@@ -480,19 +483,18 @@ function recursiveMerge(target, src) {
}
}
module.exports = {
buildIntoButDoNotClobber: function(objects, target) {
include(target, objects, false, false);
},
buildIntoAndClobber: function(objects, target) {
include(target, objects, true, false);
},
buildIntoAndMerge: function(objects, target) {
include(target, objects, true, true);
},
recursiveMerge: recursiveMerge,
assignOrWrapInDeprecateGetter: assignOrWrapInDeprecateGetter
exports.buildIntoButDoNotClobber = function(objects, target) {
include(target, objects, false, false);
};
exports.buildIntoAndClobber = function(objects, target) {
include(target, objects, true, false);
};
exports.buildIntoAndMerge = function(objects, target) {
include(target, objects, true, true);
};
exports.recursiveMerge = recursiveMerge;
exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
exports.replaceHookForTesting = function() {};
});
@@ -772,176 +774,6 @@ module.exports = {
};
});
// file: lib/common/common.js
define("cordova/common", function(require, exports, module) {
module.exports = {
defaults: {
cordova: {
path: 'cordova',
children: {
exec: {
path: 'cordova/exec'
},
logger: {
path: 'cordova/plugin/logger'
}
}
},
Cordova: {
children: {
exec: {
path: 'cordova/exec'
}
}
},
open : {
path: 'cordova/plugin/InAppBrowser'
},
navigator: {
children: {
notification: {
path: 'cordova/plugin/notification'
},
accelerometer: {
path: 'cordova/plugin/accelerometer'
},
battery: {
path: 'cordova/plugin/battery'
},
camera:{
path: 'cordova/plugin/Camera'
},
compass:{
path: 'cordova/plugin/compass'
},
contacts: {
path: 'cordova/plugin/contacts'
},
device:{
children:{
capture: {
path: 'cordova/plugin/capture'
}
}
},
geolocation: {
path: 'cordova/plugin/geolocation'
},
globalization: {
path: 'cordova/plugin/globalization'
},
network: {
children: {
connection: {
path: 'cordova/plugin/network',
deprecated: 'navigator.network.connection is deprecated. Use navigator.connection instead.'
}
}
},
splashscreen: {
path: 'cordova/plugin/splashscreen'
}
}
},
Acceleration: {
path: 'cordova/plugin/Acceleration'
},
Camera:{
path: 'cordova/plugin/CameraConstants'
},
CameraPopoverOptions: {
path: 'cordova/plugin/CameraPopoverOptions'
},
CaptureError: {
path: 'cordova/plugin/CaptureError'
},
CaptureAudioOptions:{
path: 'cordova/plugin/CaptureAudioOptions'
},
CaptureImageOptions: {
path: 'cordova/plugin/CaptureImageOptions'
},
CaptureVideoOptions: {
path: 'cordova/plugin/CaptureVideoOptions'
},
CompassHeading:{
path: 'cordova/plugin/CompassHeading'
},
CompassError:{
path: 'cordova/plugin/CompassError'
},
ConfigurationData: {
path: 'cordova/plugin/ConfigurationData'
},
Connection: {
path: 'cordova/plugin/Connection'
},
Contact: {
path: 'cordova/plugin/Contact'
},
ContactAddress: {
path: 'cordova/plugin/ContactAddress'
},
ContactError: {
path: 'cordova/plugin/ContactError'
},
ContactField: {
path: 'cordova/plugin/ContactField'
},
ContactFindOptions: {
path: 'cordova/plugin/ContactFindOptions'
},
ContactName: {
path: 'cordova/plugin/ContactName'
},
ContactOrganization: {
path: 'cordova/plugin/ContactOrganization'
},
Coordinates: {
path: 'cordova/plugin/Coordinates'
},
device: {
path: 'cordova/plugin/device'
},
GlobalizationError: {
path: 'cordova/plugin/GlobalizationError'
},
Media: {
path: 'cordova/plugin/Media'
},
MediaError: {
path: 'cordova/plugin/MediaError'
},
MediaFile: {
path: 'cordova/plugin/MediaFile'
},
MediaFileData:{
path: 'cordova/plugin/MediaFileData'
},
Position: {
path: 'cordova/plugin/Position'
},
PositionError: {
path: 'cordova/plugin/PositionError'
},
ProgressEvent: {
path: 'cordova/plugin/ProgressEvent'
}
},
clobbers: {
navigator: {
children: {
connection: {
path: 'cordova/plugin/network'
}
}
}
}
};
});
// file: lib/android/exec.js
define("cordova/exec", function(require, exports, module) {
@@ -1220,9 +1052,9 @@ function prepareNamespace(symbolPath, context) {
var parts = symbolPath.split('.');
var cur = context;
for (var i = 0, part; part = parts[i]; ++i) {
cur[part] = cur[part] || {};
cur = cur[part] = cur[part] || {};
}
return cur[parts[i-1]];
return cur;
}
exports.mapModules = function(context) {
@@ -1244,7 +1076,7 @@ exports.mapModules = function(context) {
if (strategy == 'm' && target) {
builder.recursiveMerge(target, module);
} else if ((strategy == 'd' && !target) || (strategy != 'd')) {
if (target) {
if (!(symbolPath in origSymbols)) {
origSymbols[symbolPath] = target;
}
builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
@@ -1290,6 +1122,8 @@ module.exports = {
modulemapper = require('cordova/modulemapper');
modulemapper.loadMatchingModules(/cordova.*\/symbols$/);
modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
modulemapper.mapModules(window);
// Inject a listener for the backbutton on the document.
@@ -1304,88 +1138,11 @@ module.exports = {
cordova.addDocumentEventHandler('menubutton');
cordova.addDocumentEventHandler('searchbutton');
// Figure out if we need to shim-in localStorage and WebSQL
// support from the native side.
var storage = require('cordova/plugin/android/storage');
// First patch WebSQL if necessary
if (typeof window.openDatabase == 'undefined') {
// Not defined, create an openDatabase function for all to use!
window.openDatabase = storage.openDatabase;
} else {
// Defined, but some Android devices will throw a SECURITY_ERR -
// so we wrap the whole thing in a try-catch and shim in our own
// if the device has Android bug 16175.
var originalOpenDatabase = window.openDatabase;
window.openDatabase = function(name, version, desc, size) {
var db = null;
try {
db = originalOpenDatabase(name, version, desc, size);
}
catch (ex) {
if (ex.code === 18) {
db = null;
} else {
throw ex;
}
}
if (db === null) {
return storage.openDatabase(name, version, desc, size);
}
else {
return db;
}
};
}
// Patch localStorage if necessary
if (typeof window.localStorage == 'undefined' || window.localStorage === null) {
window.localStorage = new storage.CupcakeLocalStorage();
}
// Let native code know we are all done on the JS side.
// Native code will then un-hide the WebView.
channel.join(function() {
exec(null, null, "App", "show", []);
}, [channel.onCordovaReady]);
},
clobbers: {
navigator: {
children: {
app:{
path: "cordova/plugin/android/app"
}
}
},
File: { // exists natively on Android WebView, override
path: "cordova/plugin/File"
},
FileReader: { // exists natively on Android WebView, override
path: "cordova/plugin/FileReader"
},
FileError: { //exists natively on Android WebView on Android 4.x
path: "cordova/plugin/FileError"
},
MediaError: { // exists natively on Android WebView on Android 4.x
path: "cordova/plugin/MediaError"
},
open: {
path: "cordova/plugin/InAppBrowser"
}
},
merges: {
device: {
path: 'cordova/plugin/android/device'
},
navigator: {
children: {
notification: {
path: 'cordova/plugin/android/notification'
}
}
}
}
};
@@ -1410,7 +1167,8 @@ define("cordova/plugin/Camera", function(require, exports, module) {
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
Camera = require('cordova/plugin/CameraConstants');
Camera = require('cordova/plugin/CameraConstants'),
CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle');
var cameraExport = {};
@@ -1450,6 +1208,7 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) {
mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions];
exec(successCallback, errorCallback, "Camera", "takePicture", args);
return new CameraPopoverHandle();
};
cameraExport.cleanup = function(successCallback, errorCallback) {
@@ -1494,6 +1253,24 @@ module.exports = {
});
// file: lib/common/plugin/CameraPopoverHandle.js
define("cordova/plugin/CameraPopoverHandle", function(require, exports, module) {
var exec = require('cordova/exec');
/**
* A handle to an image picker popover.
*/
var CameraPopoverHandle = function() {
this.setPosition = function(popoverOptions) {
console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
};
};
module.exports = CameraPopoverHandle;
});
// file: lib/common/plugin/CameraPopoverOptions.js
define("cordova/plugin/CameraPopoverOptions", function(require, exports, module) {
@@ -1619,9 +1396,9 @@ module.exports = CompassError;
define("cordova/plugin/CompassHeading", function(require, exports, module) {
var CompassHeading = function(magneticHeading, trueHeading, headingAccuracy, timestamp) {
this.magneticHeading = magneticHeading || null;
this.trueHeading = trueHeading || null;
this.headingAccuracy = headingAccuracy || null;
this.magneticHeading = magneticHeading;
this.trueHeading = trueHeading;
this.headingAccuracy = headingAccuracy;
this.timestamp = timestamp || new Date().getTime();
};
@@ -1663,6 +1440,7 @@ module.exports = {
CELL_2G: "2g",
CELL_3G: "3g",
CELL_4G: "4g",
CELL:"cellular",
NONE: "none"
};
@@ -2993,11 +2771,12 @@ define("cordova/plugin/FileTransferError", function(require, exports, module) {
* FileTransferError
* @constructor
*/
var FileTransferError = function(code, source, target, status) {
var FileTransferError = function(code, source, target, status, body) {
this.code = code || null;
this.source = source || null;
this.target = target || null;
this.http_status = status || null;
this.body = body || null;
};
FileTransferError.FILE_NOT_FOUND_ERR = 1;
@@ -3401,8 +3180,6 @@ module.exports = function(strUrl, strWindowName, strWindowFeatures) {
return iab;
};
//Export the original open so it can be used if needed
module.exports._orig = window.open;
});
@@ -3973,6 +3750,17 @@ module.exports = accelerometer;
});
// file: lib/common/plugin/accelerometer/symbols.js
define("cordova/plugin/accelerometer/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.defaults('cordova/plugin/Acceleration', 'Acceleration');
modulemapper.defaults('cordova/plugin/accelerometer', 'navigator.accelerometer');
});
// file: lib/android/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) {
@@ -4477,100 +4265,57 @@ var DroidDB_openDatabase = function(name, version, display_name, size) {
return db;
};
/**
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
* TODO: Do similar for sessionStorage.
* @constructor
*/
var CupcakeLocalStorage = function() {
channel.waitForInitialization("cupcakeStorage");
try {
this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
var storage = {};
this.length = 0;
function setLength (length) {
this.length = length;
localStorage.length = length;
}
this.db.transaction(
function (transaction) {
var i;
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
transaction.executeSql('SELECT * FROM storage', [], function(tx, result) {
for(var i = 0; i < result.rows.length; i++) {
storage[result.rows.item(i).id] = result.rows.item(i).body;
}
setLength(result.rows.length);
channel.initializationComplete("cupcakeStorage");
});
},
function (err) {
utils.alert(err.message);
}
);
this.setItem = function(key, val) {
if (typeof(storage[key])=='undefined') {
this.length++;
}
storage[key] = val;
this.db.transaction(
function (transaction) {
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
transaction.executeSql('REPLACE INTO storage (id, body) values(?,?)', [key,val]);
}
);
};
this.getItem = function(key) {
return storage[key];
};
this.removeItem = function(key) {
delete storage[key];
this.length--;
this.db.transaction(
function (transaction) {
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
transaction.executeSql('DELETE FROM storage where id=?', [key]);
}
);
};
this.clear = function() {
storage = {};
this.length = 0;
this.db.transaction(
function (transaction) {
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
transaction.executeSql('DELETE FROM storage', []);
}
);
};
this.key = function(index) {
var i = 0;
for (var j in storage) {
if (i==index) {
return j;
} else {
i++;
}
}
return null;
};
} catch(e) {
utils.alert("Database error "+e+".");
return;
}
};
module.exports = {
openDatabase:DroidDB_openDatabase,
CupcakeLocalStorage:CupcakeLocalStorage,
failQuery:failQuery,
completeQuery:completeQuery
};
});
// file: lib/android/plugin/android/storage/openDatabase.js
define("cordova/plugin/android/storage/openDatabase", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper'),
storage = require('cordova/plugin/android/storage');
var originalOpenDatabase = modulemapper.getOriginalSymbol(window, 'openDatabase');
module.exports = function(name, version, desc, size) {
// First patch WebSQL if necessary
if (!originalOpenDatabase) {
// Not defined, create an openDatabase function for all to use!
return storage.openDatabase.apply(this, arguments);
}
// Defined, but some Android devices will throw a SECURITY_ERR -
// so we wrap the whole thing in a try-catch and shim in our own
// if the device has Android bug 16175.
try {
return originalOpenDatabase(name, version, desc, size);
} catch (ex) {
if (ex.code !== 18) {
throw ex;
}
}
return storage.openDatabase(name, version, desc, size);
};
});
// file: lib/android/plugin/android/storage/symbols.js
define("cordova/plugin/android/storage/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/android/storage/openDatabase', 'openDatabase');
});
// file: lib/common/plugin/battery.js
@@ -4657,6 +4402,28 @@ module.exports = battery;
});
// file: lib/common/plugin/battery/symbols.js
define("cordova/plugin/battery/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.defaults('cordova/plugin/battery', 'navigator.battery');
});
// file: lib/common/plugin/camera/symbols.js
define("cordova/plugin/camera/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.defaults('cordova/plugin/Camera', 'navigator.camera');
modulemapper.defaults('cordova/plugin/CameraConstants', 'Camera');
modulemapper.defaults('cordova/plugin/CameraPopoverOptions', 'CameraPopoverOptions');
});
// file: lib/common/plugin/capture.js
define("cordova/plugin/capture", function(require, exports, module) {
@@ -4735,6 +4502,22 @@ module.exports = new Capture();
});
// file: lib/common/plugin/capture/symbols.js
define("cordova/plugin/capture/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/CaptureError', 'CaptureError');
modulemapper.clobbers('cordova/plugin/CaptureAudioOptions', 'CaptureAudioOptions');
modulemapper.clobbers('cordova/plugin/CaptureImageOptions', 'CaptureImageOptions');
modulemapper.clobbers('cordova/plugin/CaptureVideoOptions', 'CaptureVideoOptions');
modulemapper.clobbers('cordova/plugin/ConfigurationData', 'ConfigurationData');
modulemapper.clobbers('cordova/plugin/MediaFile', 'MediaFile');
modulemapper.clobbers('cordova/plugin/MediaFileData', 'MediaFileData');
modulemapper.clobbers('cordova/plugin/capture', 'navigator.device.capture');
});
// file: lib/common/plugin/compass.js
define("cordova/plugin/compass", function(require, exports, module) {
@@ -4822,6 +4605,18 @@ module.exports = compass;
});
// file: lib/common/plugin/compass/symbols.js
define("cordova/plugin/compass/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/CompassHeading', 'CompassHeading');
modulemapper.clobbers('cordova/plugin/CompassError', 'CompassError');
modulemapper.clobbers('cordova/plugin/compass', 'navigator.compass');
});
// file: lib/common/plugin/console-via-logger.js
define("cordova/plugin/console-via-logger", function(require, exports, module) {
@@ -5055,6 +4850,23 @@ module.exports = contacts;
});
// file: lib/common/plugin/contacts/symbols.js
define("cordova/plugin/contacts/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/contacts', 'navigator.contacts');
modulemapper.clobbers('cordova/plugin/Contact', 'Contact');
modulemapper.clobbers('cordova/plugin/ContactAddress', 'ContactAddress');
modulemapper.clobbers('cordova/plugin/ContactError', 'ContactError');
modulemapper.clobbers('cordova/plugin/ContactField', 'ContactField');
modulemapper.clobbers('cordova/plugin/ContactFindOptions', 'ContactFindOptions');
modulemapper.clobbers('cordova/plugin/ContactName', 'ContactName');
modulemapper.clobbers('cordova/plugin/ContactOrganization', 'ContactOrganization');
});
// file: lib/common/plugin/device.js
define("cordova/plugin/device", function(require, exports, module) {
@@ -5114,6 +4926,17 @@ module.exports = new Device();
});
// file: lib/android/plugin/device/symbols.js
define("cordova/plugin/device/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/device', 'device');
modulemapper.merges('cordova/plugin/android/device', 'device');
});
// file: lib/common/plugin/echo.js
define("cordova/plugin/echo", function(require, exports, module) {
@@ -5160,20 +4983,30 @@ module.exports = function(exportFunc) {
exportFunc('cordova/plugin/FileError', 'FileError');
exportFunc('cordova/plugin/FileReader', 'FileReader');
exportFunc('cordova/plugin/FileSystem', 'FileSystem');
exportFunc('cordova/plugin/FileTransfer', 'FileTransfer');
exportFunc('cordova/plugin/FileTransferError', 'FileTransferError');
exportFunc('cordova/plugin/FileUploadOptions', 'FileUploadOptions');
exportFunc('cordova/plugin/FileUploadResult', 'FileUploadResult');
exportFunc('cordova/plugin/FileWriter', 'FileWriter');
exportFunc('cordova/plugin/Flags', 'Flags');
exportFunc('cordova/plugin/LocalFileSystem', 'LocalFileSystem');
exportFunc('cordova/plugin/Metadata', 'Metadata');
exportFunc('cordova/plugin/ProgressEvent', 'ProgressEvent');
exportFunc('cordova/plugin/requestFileSystem', 'requestFileSystem');
exportFunc('cordova/plugin/resolveLocalFileSystemURI', 'resolveLocalFileSystemURI');
};
});
// file: lib/common/plugin/filetransfer/symbols.js
define("cordova/plugin/filetransfer/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/FileTransfer', 'FileTransfer');
modulemapper.clobbers('cordova/plugin/FileTransferError', 'FileTransferError');
});
// file: lib/common/plugin/geolocation.js
define("cordova/plugin/geolocation", function(require, exports, module) {
@@ -5370,6 +5203,19 @@ module.exports = geolocation;
});
// file: lib/common/plugin/geolocation/symbols.js
define("cordova/plugin/geolocation/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.defaults('cordova/plugin/geolocation', 'navigator.geolocation');
modulemapper.clobbers('cordova/plugin/PositionError', 'PositionError');
modulemapper.clobbers('cordova/plugin/Position', 'Position');
modulemapper.clobbers('cordova/plugin/Coordinates', 'Coordinates');
});
// file: lib/common/plugin/globalization.js
define("cordova/plugin/globalization", function(require, exports, module) {
@@ -5746,6 +5592,27 @@ module.exports = globalization;
});
// file: lib/common/plugin/globalization/symbols.js
define("cordova/plugin/globalization/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/globalization', 'navigator.globalization');
modulemapper.clobbers('cordova/plugin/GlobalizationError', 'GlobalizationError');
});
// file: lib/android/plugin/inappbrowser/symbols.js
define("cordova/plugin/inappbrowser/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/InAppBrowser', 'open');
});
// file: lib/common/plugin/logger.js
define("cordova/plugin/logger", function(require, exports, module) {
@@ -5974,6 +5841,27 @@ document.addEventListener("deviceready", logger.__onDeviceReady, false);
});
// file: lib/common/plugin/logger/symbols.js
define("cordova/plugin/logger/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/logger', 'cordova.logger');
});
// file: lib/android/plugin/media/symbols.js
define("cordova/plugin/media/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.defaults('cordova/plugin/Media', 'Media');
modulemapper.clobbers('cordova/plugin/MediaError', 'MediaError');
});
// file: lib/common/plugin/network.js
define("cordova/plugin/network", function(require, exports, module) {
@@ -6046,6 +5934,18 @@ module.exports = me;
});
// file: lib/common/plugin/networkstatus/symbols.js
define("cordova/plugin/networkstatus/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/network', 'navigator.network.connection', 'navigator.network.connection is deprecated. Use navigator.connection instead.');
modulemapper.clobbers('cordova/plugin/network', 'navigator.connection');
modulemapper.defaults('cordova/plugin/Connection', 'Connection');
});
// file: lib/common/plugin/notification.js
define("cordova/plugin/notification", function(require, exports, module) {
@@ -6108,6 +6008,17 @@ module.exports = {
});
// file: lib/android/plugin/notification/symbols.js
define("cordova/plugin/notification/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/notification', 'navigator.notification');
modulemapper.merges('cordova/plugin/android/notification', 'navigator.notification');
});
// file: lib/common/plugin/requestFileSystem.js
define("cordova/plugin/requestFileSystem", function(require, exports, module) {
@@ -6221,6 +6132,29 @@ module.exports = splashscreen;
});
// file: lib/common/plugin/splashscreen/symbols.js
define("cordova/plugin/splashscreen/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
modulemapper.clobbers('cordova/plugin/splashscreen', 'navigator.splashscreen');
});
// file: lib/common/symbols.js
define("cordova/symbols", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
// Use merges here in case others symbols files depend on this running first,
// but fail to declare the dependency with a require().
modulemapper.merges('cordova', 'cordova');
modulemapper.clobbers('cordova/exec', 'cordova.exec');
modulemapper.clobbers('cordova/exec', 'Cordova.exec');
});
// file: lib/common/utils.js
define("cordova/utils", function(require, exports, module) {
@@ -6489,14 +6423,8 @@ window.cordova = require('cordova');
*/
channel.join(function() {
var builder = require('cordova/builder'),
base = require('cordova/common'),
platform = require('cordova/platform');
// Drop the common globals into the window object, but be nice and don't overwrite anything.
builder.buildIntoButDoNotClobber(base.defaults, context);
builder.buildIntoAndClobber(base.clobbers, context);
builder.buildIntoAndMerge(base.merges, context);
builder.buildIntoButDoNotClobber(platform.defaults, context);
builder.buildIntoAndClobber(platform.clobbers, context);
builder.buildIntoAndMerge(platform.merges, context);

View File

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

View File

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

View File

@@ -58,6 +58,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private static final int DATA_URL = 0; // Return base64 encoded string
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
private static final int CAMERA = 1; // Take picture from camera
@@ -310,7 +311,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
// If sending filename back
else if (destType == FILE_URI) {
else if (destType == FILE_URI || destType == NATIVE_URI) {
if (!this.saveToPhotoAlbum) {
uri = Uri.fromFile(new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), System.currentTimeMillis() + ".jpg"));
} else {
@@ -388,9 +389,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
else {
// This is a special case to just return the path as no scaling,
// rotating or compression needs to be done
// rotating, nor compressing needs to be done
if (this.targetHeight == -1 && this.targetWidth == -1 &&
this.mQuality == 100 && destType == FILE_URI && !this.correctOrientation) {
(destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) {
this.callbackContext.success(uri.toString());
} else {
// Get the path to the image. Makes loading so much easier.
@@ -434,7 +435,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
// If sending filename back
else if (destType == FILE_URI) {
else if (destType == FILE_URI || destType == NATIVE_URI) {
// Do we need to scale the returned file
if (this.targetHeight > 0 && this.targetWidth > 0) {
try {
@@ -571,7 +572,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
//CB-2292: WTF? Why is the width null?
if(options.outWidth == 0 || options.outHeight == 0)
{
return null;
}
// determine the correct aspect ratio
int[] widthHeight = calculateAspectRatio(options.outWidth, options.outHeight);

View File

@@ -35,6 +35,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.content.res.XmlResourceParser;
import android.graphics.Color;
import android.util.Log;
@@ -103,12 +104,56 @@ public class Config {
}
else if (strNode.equals("preference")) {
String name = xml.getAttributeValue(null, "name");
String value = xml.getAttributeValue(null, "value");
/* Java 1.6 does not support switch-based strings
Java 7 does, but we're using Dalvik, which is apparently not Java.
Since we're reading XML, this has to be an ugly if/else.
Also, due to cast issues, each of them has to call their separate putExtra!
Wheee!!! Isn't Java FUN!?!?!?
Note: We should probably pass in the classname for the variable splash on splashscreen!
*/
if(name.equals("splashscreen")) {
String value = xml.getAttributeValue(null, "value");
int resource = 0;
if (value != null)
{
value = "splash";
}
resource = action.getResources().getIdentifier(value, "drawable", action.getPackageName());
action.getIntent().putExtra(name, resource);
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + value);
}
else if(name.equals("backgroundColor")) {
int value = xml.getAttributeIntValue(null, "value", Color.BLACK);
action.getIntent().putExtra(name, value);
LOG.i("CordovaLog", "Found preference for %s=%d", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + Integer.toString(value));
}
else if(name.equals("loadUrlTimeoutValue")) {
int value = xml.getAttributeIntValue(null, "value", 20000);
action.getIntent().putExtra(name, value);
LOG.i("CordovaLog", "Found preference for %s=%d", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + Integer.toString(value));
}
else if(name.equals("keepRunning"))
{
boolean value = xml.getAttributeValue(null, "value").equals("true");
action.getIntent().putExtra(name, value);
}
else
{
String value = xml.getAttributeValue(null, "value");
action.getIntent().putExtra(name, value);
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + value);
}
/*
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + value);
action.getIntent().putExtra(name, value);
*/
}
else if (strNode.equals("content")) {
String src = xml.getAttributeValue(null, "src");

View File

@@ -18,7 +18,6 @@ package org.apache.cordova;
import java.util.HashMap;
import android.content.Context;
import android.util.Log;
import android.webkit.WebView;

View File

@@ -860,8 +860,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
im.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im._ID)));
im.put("pref", false); // Android does not store pref attribute
im.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
String type = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL));
im.put("type", getImType(new Integer(type).intValue()));
im.put("type", getImType(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL))));
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}

View File

@@ -24,12 +24,10 @@ import org.json.JSONArray;
import org.json.JSONException;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;

View File

@@ -27,7 +27,6 @@ import java.util.Stack;
import org.apache.cordova.Config;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.api.PluginResult;
@@ -263,6 +262,7 @@ public class CordovaWebView extends WebView {
settings.setDatabaseEnabled(true);
String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabasePath(databasePath);
settings.setGeolocationDatabasePath(databasePath);
// Enable DOM storage
settings.setDomStorageEnabled(true);
@@ -270,6 +270,13 @@ public class CordovaWebView extends WebView {
// Enable built-in geolocation
settings.setGeolocationEnabled(true);
// Enable AppCache
// Fix for CB-2282
settings.setAppCacheMaxSize(5 * 1048576);
String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setAppCachePath(pathToCache);
settings.setAppCacheEnabled(true);
// Fix for CB-1405
// Google issue 4641
this.updateUserAgentString();
@@ -554,15 +561,14 @@ public class CordovaWebView extends WebView {
// 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)
if (super.canGoBack()) {
if (super.canGoBack() && this.useBrowserHistory) {
printBackForwardList();
super.goBack();
return true;
}
// If our managed history has prev url
if (this.urls.size() > 1 && !this.useBrowserHistory) {
else if (this.urls.size() > 1 && !this.useBrowserHistory) {
this.urls.pop(); // Pop current url
String url = this.urls.pop(); // Pop prev url that we want to load, since it will be added back by loadUrl()
this.loadUrl(url);
@@ -578,10 +584,10 @@ public class CordovaWebView extends WebView {
* @return
*/
public boolean canGoBack() {
if (super.canGoBack()) {
if (super.canGoBack() && this.useBrowserHistory) {
return true;
}
if (this.urls.size() > 1) {
else if (this.urls.size() > 1) {
return true;
}
return false;
@@ -749,7 +755,9 @@ public class CordovaWebView extends WebView {
// If not, then invoke default behaviour
else {
//this.activityState = ACTIVITY_EXITING;
return false;
//return false;
// If they hit back button when app is initializing, app should exit instead of hang until initilazation (CB2-458)
this.cordova.getActivity().finish();
}
}
}
@@ -847,7 +855,8 @@ public class CordovaWebView extends WebView {
public void handleDestroy()
{
// Send destroy event to JavaScript
this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
// Since baseUrl is set in loadUrlIntoView, if user hit Back button before loadUrl was called, we'll get an NPE on baseUrl (CB-2458)
this.loadUrlIntoView("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
// Load blank page so that JavaScript onunload is called
this.loadUrl("about:blank");
@@ -910,11 +919,14 @@ public class CordovaWebView extends WebView {
{
WebBackForwardList currentList = this.copyBackForwardList();
WebHistoryItem item = currentList.getItemAtIndex(0);
String url = item.getUrl();
String currentUrl = this.getUrl();
LOG.d(TAG, "The current URL is: " + currentUrl);
LOG.d(TAG, "The URL at item 0 is:" + url);
return currentUrl.equals(url);
if( item!=null){ // Null-fence in case they haven't called loadUrl yet (CB-2458)
String url = item.getUrl();
String currentUrl = this.getUrl();
LOG.d(TAG, "The current URL is: " + currentUrl);
LOG.d(TAG, "The URL at item 0 is:" + url);
return currentUrl.equals(url);
}
return false;
}
public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {

View File

@@ -230,6 +230,10 @@ public class CordovaWebViewClient extends WebViewClient {
AuthenticationToken token = this.getAuthenticationToken(host, realm);
if (token != null) {
handler.proceed(token.getUserName(), token.getPassword());
}
else {
// Handle 401 like we'd normally do!
super.onReceivedHttpAuthRequest(view, handler, host, realm);
}
}

View File

@@ -24,7 +24,6 @@ import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -39,7 +38,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin {
public static final String TAG = "Device";
public static String cordovaVersion = "2.4.0rc1"; // Cordova version
public static String cordovaVersion = "2.5.0"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID

View File

@@ -51,7 +51,6 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
@@ -591,6 +590,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param value
*/
public void setBooleanProperty(String name, boolean value) {
Log.d(TAG, "Setting boolean properties in DroidGap will be deprecated in 3.0 on July 2013, please use config.xml");
this.getIntent().putExtra(name, value);
}
@@ -601,6 +601,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param value
*/
public void setIntegerProperty(String name, int value) {
Log.d(TAG, "Setting integer properties in DroidGap will be deprecated in 3.1 on August 2013, please use config.xml");
this.getIntent().putExtra(name, value);
}
@@ -611,6 +612,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param value
*/
public void setStringProperty(String name, String value) {
Log.d(TAG, "Setting string properties in DroidGap will be deprecated in 3.0 on July 2013, please use config.xml");
this.getIntent().putExtra(name, value);
}
@@ -621,6 +623,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param value
*/
public void setDoubleProperty(String name, double value) {
Log.d(TAG, "Setting double properties in DroidGap will be deprecated in 3.0 on July 2013, please use config.xml");
this.getIntent().putExtra(name, value);
}

View File

@@ -20,7 +20,6 @@ package org.apache.cordova;
import android.webkit.JavascriptInterface;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.api.PluginResult;
import org.json.JSONException;
/**

View File

@@ -20,7 +20,6 @@ package org.apache.cordova;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -33,6 +32,7 @@ import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -77,6 +77,7 @@ public class FileTransfer extends CordovaPlugin {
private static final class RequestContext {
String source;
String target;
File targetFile;
CallbackContext callbackContext;
InputStream currentInputStream;
OutputStream currentOutputStream;
@@ -200,7 +201,7 @@ public class FileTransfer extends CordovaPlugin {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
return;
}
final boolean useHttps = url.getProtocol().toLowerCase().equals("https");
final boolean useHttps = url.getProtocol().equals("https");
final RequestContext context = new RequestContext(source, target, callbackContext);
synchronized (activeRequests) {
@@ -215,6 +216,8 @@ public class FileTransfer extends CordovaPlugin {
HttpURLConnection conn = null;
HostnameVerifier oldHostnameVerifier = null;
SSLSocketFactory oldSocketFactory = null;
int totalBytes = 0;
int fixedLength = -1;
try {
// Create return object
FileUploadResult result = new FileUploadResult();
@@ -256,7 +259,6 @@ public class FileTransfer extends CordovaPlugin {
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
// Set the cookies on the response
@@ -289,38 +291,35 @@ public class FileTransfer extends CordovaPlugin {
* Store the non-file portions of the multipart data as a string, so that we can add it
* to the contentSize, since it is part of the body of the HTTP request.
*/
String extraParams = "";
StringBuilder beforeData = new StringBuilder();
try {
for (Iterator<?> iter = params.keys(); iter.hasNext();) {
Object key = iter.next();
if(!String.valueOf(key).equals("headers"))
{
extraParams += LINE_START + BOUNDARY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + key.toString() + "\";";
extraParams += LINE_END + LINE_END;
extraParams += params.getString(key.toString());
extraParams += LINE_END;
beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append('"');
beforeData.append(LINE_END).append(LINE_END);
beforeData.append(params.getString(key.toString()));
beforeData.append(LINE_END);
}
}
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
extraParams += LINE_START + BOUNDARY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
byte[] extraBytes = extraParams.getBytes("UTF-8");
String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
String tailParams = LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END;
byte[] fileNameBytes = fileName.getBytes("UTF-8");
beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
beforeData.append("Content-Disposition: form-data; name=\"").append(fileKey).append("\";");
beforeData.append(" filename=\"").append(fileName).append('"').append(LINE_END);
beforeData.append("Content-Type: ").append(mimeType).append(LINE_END).append(LINE_END);
byte[] beforeDataBytes = beforeData.toString().getBytes("UTF-8");
byte[] tailParamsBytes = (LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END).getBytes("UTF-8");
// Get a input stream of the file on the phone
InputStream sourceInputStream = getPathFromUri(source);
int stringLength = extraBytes.length + midParams.length() + tailParams.length() + fileNameBytes.length;
Log.d(LOG_TAG, "String Length: " + stringLength);
int fixedLength = -1;
int stringLength = beforeDataBytes.length + tailParamsBytes.length;
if (sourceInputStream instanceof FileInputStream) {
fixedLength = (int) ((FileInputStream)sourceInputStream).getChannel().size() + stringLength;
progress.setLengthComputable(true);
@@ -332,7 +331,7 @@ public class FileTransfer extends CordovaPlugin {
// It also causes OOM if HTTPS is used, even on newer devices.
boolean useChunkedMode = chunkedMode && (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO || useHttps);
useChunkedMode = useChunkedMode || (fixedLength == -1);
if (useChunkedMode) {
conn.setChunkedStreamingMode(MAX_BUFFER_SIZE);
// Although setChunkedStreamingMode sets this header, setting it explicitly here works
@@ -342,19 +341,20 @@ public class FileTransfer extends CordovaPlugin {
conn.setFixedLengthStreamingMode(fixedLength);
}
DataOutputStream dos = null;
conn.connect();
OutputStream sendStream = null;
try {
dos = new DataOutputStream( conn.getOutputStream() );
sendStream = conn.getOutputStream();
synchronized (context) {
if (context.aborted) {
return;
}
context.currentOutputStream = dos;
context.currentOutputStream = sendStream;
}
//We don't want to change encoding, we just want this to write for all Unicode.
dos.write(extraBytes);
dos.write(fileNameBytes);
dos.writeBytes(midParams);
sendStream.write(beforeDataBytes);
totalBytes += beforeDataBytes.length;
// create a buffer of maximum size
int bytesAvailable = sourceInputStream.available();
@@ -363,13 +363,12 @@ public class FileTransfer extends CordovaPlugin {
// read file and write it into form...
int bytesRead = sourceInputStream.read(buffer, 0, bufferSize);
long totalBytes = 0;
long prevBytesRead = 0;
while (bytesRead > 0) {
totalBytes += bytesRead;
result.setBytesSent(totalBytes);
dos.write(buffer, 0, bufferSize);
sendStream.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
if (totalBytes > prevBytesRead + 102400) {
prevBytesRead = totalBytes;
Log.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
@@ -386,17 +385,21 @@ public class FileTransfer extends CordovaPlugin {
}
// send multipart form data necessary after file data...
dos.writeBytes(tailParams);
dos.flush();
sendStream.write(tailParamsBytes);
totalBytes += tailParamsBytes.length;
sendStream.flush();
} finally {
safeClose(sourceInputStream);
safeClose(dos);
safeClose(sendStream);
}
context.currentOutputStream = null;
Log.d(LOG_TAG, "Sent " + totalBytes + " of " + fixedLength);
//------------------ read the SERVER RESPONSE
String responseString;
int responseCode = conn.getResponseCode();
Log.d(LOG_TAG, "response code: " + responseCode);
Log.d(LOG_TAG, "response headers: " + conn.getHeaderFields());
InputStream inStream = null;
try {
inStream = getInputStream(conn);
@@ -407,8 +410,7 @@ public class FileTransfer extends CordovaPlugin {
context.currentInputStream = inStream;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(1024, conn.getContentLength()));
byte[] buffer = new byte[1024];
int bytesRead = 0;
// write bytes to file
@@ -436,6 +438,7 @@ public class FileTransfer extends CordovaPlugin {
} catch (IOException e) {
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
Log.e(LOG_TAG, error.toString(), e);
Log.e(LOG_TAG, "Failed after uploading " + totalBytes + " of " + fixedLength + " bytes.");
context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
@@ -458,8 +461,6 @@ public class FileTransfer extends CordovaPlugin {
https.setHostnameVerifier(oldHostnameVerifier);
https.setSSLSocketFactory(oldSocketFactory);
}
conn.disconnect();
}
}
}
@@ -475,7 +476,7 @@ public class FileTransfer extends CordovaPlugin {
}
}
private static InputStream getInputStream(HttpURLConnection conn) throws IOException {
private static InputStream getInputStream(URLConnection conn) throws IOException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return new DoneHandlerInputStream(conn.getInputStream());
}
@@ -526,13 +527,15 @@ public class FileTransfer extends CordovaPlugin {
return oldFactory;
}
private static JSONObject createFileTransferError(int errorCode, String source, String target, HttpURLConnection connection) {
private static JSONObject createFileTransferError(int errorCode, String source, String target, URLConnection connection) {
Integer httpStatus = null;
int httpStatus = 0;
if (connection != null) {
try {
httpStatus = connection.getResponseCode();
if (connection instanceof HttpURLConnection) {
httpStatus = ((HttpURLConnection)connection).getResponseCode();
}
} catch (IOException e) {
Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
}
@@ -601,7 +604,7 @@ public class FileTransfer extends CordovaPlugin {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
return;
}
final boolean useHttps = url.getProtocol().toLowerCase().equals("https");
final boolean useHttps = url.getProtocol().equals("https");
if (!Config.isUrlWhiteListed(source)) {
Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
@@ -621,14 +624,16 @@ public class FileTransfer extends CordovaPlugin {
if (context.aborted) {
return;
}
HttpURLConnection connection = null;
URLConnection connection = null;
HostnameVerifier oldHostnameVerifier = null;
SSLSocketFactory oldSocketFactory = null;
File file = null;
PluginResult result = null;
try {
file = getFileFromPath(target);
context.targetFile = file;
// create needed directories
File file = getFileFromPath(target);
file.getParentFile().mkdirs();
// connect to server
@@ -653,10 +658,12 @@ public class FileTransfer extends CordovaPlugin {
}
// Return a standard HTTP connection
else {
connection = (HttpURLConnection) url.openConnection();
connection = url.openConnection();
}
connection.setRequestMethod("GET");
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).setRequestMethod("GET");
}
//Add cookie support
String cookie = CookieManager.getInstance().getCookie(source);
@@ -714,22 +721,22 @@ public class FileTransfer extends CordovaPlugin {
FileUtils fileUtil = new FileUtils();
JSONObject fileEntry = fileUtil.getEntry(file);
context.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileEntry));
result = new PluginResult(PluginResult.Status.OK, fileEntry);
} catch (FileNotFoundException e) {
JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection);
Log.e(LOG_TAG, error.toString(), e);
context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IOException e) {
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection);
Log.e(LOG_TAG, error.toString(), e);
context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
context.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
result = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
} catch (Throwable e) {
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection);
Log.e(LOG_TAG, error.toString(), e);
context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} finally {
synchronized (activeRequests) {
activeRequests.remove(objectId);
@@ -742,9 +749,16 @@ public class FileTransfer extends CordovaPlugin {
https.setHostnameVerifier(oldHostnameVerifier);
https.setSSLSocketFactory(oldSocketFactory);
}
connection.disconnect();
}
if (result == null) {
result = new PluginResult(PluginResult.Status.ERROR, createFileTransferError(CONNECTION_ERR, source, target, connection));
}
// Remove incomplete download.
if (result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) {
file.delete();
}
context.sendPluginResult(result);
}
}
});
@@ -807,6 +821,10 @@ public class FileTransfer extends CordovaPlugin {
context = activeRequests.remove(objectId);
}
if (context != null) {
File file = context.targetFile;
if (file != null) {
file.delete();
}
// Trigger the abort callback immediately to minimize latency between it and abort() being called.
JSONObject error = createFileTransferError(ABORTED_ERR, context.source, context.target, -1);
synchronized (context) {

View File

@@ -43,7 +43,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
//import android.app.Activity;
@@ -89,7 +88,7 @@ public class FileUtils extends CordovaPlugin {
* Executes the request and returns whether the action was valid.
*
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param args JSONArray of arguments for the plugin.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return True if the action was valid, false otherwise.
*/
@@ -238,7 +237,7 @@ public class FileUtils extends CordovaPlugin {
* @param filePath the path to check
*/
private void notifyDelete(String filePath) {
String newFilePath = stripFileProtocol(filePath);
String newFilePath = getRealPathFromURI(Uri.parse(filePath), cordova);
try {
this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.Images.Media.DATA + " = ?",
@@ -342,18 +341,18 @@ public class FileUtils extends CordovaPlugin {
* @throws InvalidModificationException
* @throws EncodingException
* @throws JSONException
* @throws FileExistsException
* @throws FileExistsException
*/
private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
fileName = stripFileProtocol(fileName);
newParent = stripFileProtocol(newParent);
String newFileName = getRealPathFromURI(Uri.parse(fileName), cordova);
newParent = getRealPathFromURI(Uri.parse(newParent), cordova);
// Check for invalid file name
if (newName != null && newName.contains(":")) {
throw new EncodingException("Bad file name");
}
File source = new File(fileName);
File source = new File(newFileName);
if (!source.exists()) {
// The file/directory we are copying doesn't exist so we should fail.
@@ -385,7 +384,14 @@ public class FileUtils extends CordovaPlugin {
}
} else {
if (move) {
return moveFile(source, destination);
JSONObject newFileEntry = moveFile(source, destination);
// If we've moved a file given its content URI, we need to clean up.
if (fileName.startsWith("content://")) {
notifyDelete(fileName);
}
return newFileEntry;
} else {
return copyFile(source, destination);
}
@@ -483,7 +489,7 @@ public class FileUtils extends CordovaPlugin {
if (!destinationDir.exists()) {
if (!destinationDir.mkdir()) {
// If we can't create the directory then fail
throw new NoModificationAllowedException("Couldn't create the destination direcotry");
throw new NoModificationAllowedException("Couldn't create the destination directory");
}
}
@@ -561,8 +567,8 @@ public class FileUtils extends CordovaPlugin {
* @throws JSONException
* @throws IOException
* @throws InvalidModificationException
* @throws NoModificationAllowedException
* @throws FileExistsException
* @throws NoModificationAllowedException
* @throws FileExistsException
*/
private JSONObject moveDirectory(File srcDir, File destinationDir) throws IOException, JSONException, InvalidModificationException, NoModificationAllowedException, FileExistsException {
// Renaming a file to an existing directory should fail
@@ -742,7 +748,7 @@ public class FileUtils extends CordovaPlugin {
if (fileName.startsWith("/")) {
fp = new File(fileName);
} else {
dirPath = stripFileProtocol(dirPath);
dirPath = getRealPathFromURI(Uri.parse(dirPath), cordova);
fp = new File(dirPath + File.separator + fileName);
}
return fp;
@@ -757,7 +763,7 @@ public class FileUtils extends CordovaPlugin {
* @throws JSONException
*/
private JSONObject getParent(String filePath) throws JSONException {
filePath = stripFileProtocol(filePath);
filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
if (atRootDirectory(filePath)) {
return getEntry(filePath);
@@ -773,7 +779,7 @@ public class FileUtils extends CordovaPlugin {
* @return true if we are at the root, false otherwise.
*/
private boolean atRootDirectory(String filePath) {
filePath = stripFileProtocol(filePath);
filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache") ||
filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
@@ -803,7 +809,7 @@ public class FileUtils extends CordovaPlugin {
* @return
*/
private File createFileObject(String filePath) {
filePath = stripFileProtocol(filePath);
filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
File file = new File(filePath);
return file;
@@ -845,7 +851,7 @@ public class FileUtils extends CordovaPlugin {
metadata.put("size", file.length());
metadata.put("type", getMimeType(filePath));
metadata.put("name", file.getName());
metadata.put("fullPath", file.getAbsolutePath());
metadata.put("fullPath", filePath);
metadata.put("lastModifiedDate", file.lastModified());
return metadata;
@@ -1028,7 +1034,7 @@ public class FileUtils extends CordovaPlugin {
if (filename != null) {
// Stupid bug in getFileExtensionFromUrl when the file name has a space
// So we need to replace the space with a url encoded %20
// CB-2185: Stupid bug not putting JPG extension in the mime-type map
String url = filename.replace(" ", "%20").toLowerCase();
MimeTypeMap map = MimeTypeMap.getSingleton();
@@ -1050,10 +1056,15 @@ public class FileUtils extends CordovaPlugin {
* @param data The contents of the file.
* @param offset The position to begin writing the file.
* @throws FileNotFoundException, IOException
* @throws NoModificationAllowedException
*/
/**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException {
filename = stripFileProtocol(filename);
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException, NoModificationAllowedException {
if (filename.startsWith("content://")) {
throw new NoModificationAllowedException("Couldn't write to file given its content URI");
}
filename = getRealPathFromURI(Uri.parse(filename), cordova);
boolean append = false;
if (offset > 0) {
@@ -1079,9 +1090,14 @@ public class FileUtils extends CordovaPlugin {
* @param filename
* @param size
* @throws FileNotFoundException, IOException
* @throws NoModificationAllowedException
*/
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException {
filename = stripFileProtocol(filename);
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
if (filename.startsWith("content://")) {
throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
}
filename = getRealPathFromURI(Uri.parse(filename), cordova);
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
try {
@@ -1090,7 +1106,7 @@ public class FileUtils extends CordovaPlugin {
channel.truncate(size);
return size;
}
return raf.length();
} finally {
raf.close();
@@ -1110,7 +1126,7 @@ public class FileUtils extends CordovaPlugin {
return cordova.getActivity().getContentResolver().openInputStream(uri);
}
else {
path = stripFileProtocol(path);
path = getRealPathFromURI(Uri.parse(path), cordova);
return new FileInputStream(path);
}
}
@@ -1125,8 +1141,10 @@ public class FileUtils extends CordovaPlugin {
@SuppressWarnings("deprecation")
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) {
final String scheme = contentUri.getScheme();
if (scheme.compareTo("content") == 0) {
if (scheme == null) {
return contentUri.toString();
} else if (scheme.compareTo("content") == 0) {
String[] proj = { _DATA };
Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA);

View File

@@ -23,6 +23,7 @@ import java.util.StringTokenizer;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
@@ -48,6 +49,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
@@ -67,13 +69,14 @@ public class InAppBrowser extends CordovaPlugin {
private static final String EXIT_EVENT = "exit";
private static final String LOAD_START_EVENT = "loadstart";
private static final String LOAD_STOP_EVENT = "loadstop";
private long MAX_QUOTA = 100 * 1024 * 1024;
private Dialog dialog;
private WebView inAppWebView;
private EditText edittext;
private boolean showLocationBar = true;
private CallbackContext callbackContext;
/**
* Executes the request and returns PluginResult.
*
@@ -108,6 +111,17 @@ public class InAppBrowser extends CordovaPlugin {
|| Config.isUrlWhiteListed(url)) {
this.webView.loadUrl(url);
}
//Load the dialer
else if (url.startsWith(WebView.SCHEME_TEL))
{
try {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url));
this.cordova.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
}
}
// load in InAppBrowser
else {
result = this.showWebPage(url, features);
@@ -401,7 +415,7 @@ public class InAppBrowser extends CordovaPlugin {
// WebView
inAppWebView = new WebView(cordova.getActivity());
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
inAppWebView.setWebChromeClient(new WebChromeClient());
inAppWebView.setWebChromeClient(new InAppChromeClient());
WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
inAppWebView.setWebViewClient(client);
WebSettings settings = inAppWebView.getSettings();
@@ -468,6 +482,40 @@ public class InAppBrowser extends CordovaPlugin {
this.callbackContext.sendPluginResult(result);
}
public class InAppChromeClient extends WebChromeClient {
/**
* Handle database quota exceeded notification.
*
* @param url
* @param databaseIdentifier
* @param currentQuota
* @param estimatedSize
* @param totalUsedQuota
* @param quotaUpdater
*/
@Override
public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
{
LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
if (estimatedSize < MAX_QUOTA)
{
//increase for 1Mb
long newQuota = estimatedSize;
LOG.d(LOG_TAG, "calling quotaUpdater.updateQuota newQuota: %d", newQuota);
quotaUpdater.updateQuota(newQuota);
}
else
{
// Set the quota to whatever it is and force an error
// TODO: get docs on how to handle this properly
quotaUpdater.updateQuota(currentQuota);
}
}
}
/**
* The webview client receives notifications about appView
*/

View File

@@ -22,7 +22,6 @@ import java.io.File;
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;

View File

@@ -19,7 +19,6 @@
package org.apache.cordova.api;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import java.util.concurrent.ExecutorService;

View File

@@ -22,17 +22,13 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Intent;
import android.content.res.XmlResourceParser;
import android.util.Log;
/**
* PluginManager is exposed to JavaScript in the Cordova WebView.

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova.test" android:versionName="1.1" android:versionCode="5">
package="org.apache.cordova.test" android:versionName="1.0" android:versionCode="1">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

File diff suppressed because it is too large Load Diff

View File

@@ -45,12 +45,13 @@
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
<plugin name="Echo" value="org.apache.cordova.Echo" />
<plugin name="Globalization" value="org.apache.cordova.Globalization"/>
<plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser"/>
</plugins>
</cordova>

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<cordova>
<!--
access elements control the Android whitelist.
Domains are assumed blocked unless set otherwise
-->
<access origin="http://127.0.0.1*"/> <!-- allow local pages -->
<!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
<!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
<!-- <access origin=".*"/> Allow all domains, suggested development use only -->
<log level="DEBUG"/>
<preference name="useBrowserHistory" value="true" />
</cordova>

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<plugins>
<plugin name="App" value="org.apache.cordova.App"/>
<plugin name="Activity" value="org.apache.cordova.test.ActivityPlugin"/>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
<plugin name="Device" value="org.apache.cordova.Device"/>
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
<plugin name="File" value="org.apache.cordova.FileUtils"/>
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
</plugins>

View File

@@ -18,19 +18,21 @@
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.api.LOG;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
/**
* This class provides a service.
*/
public class ActivityPlugin extends Plugin {
public class ActivityPlugin extends CordovaPlugin {
static String TAG = "ActivityPlugin";
@@ -48,19 +50,21 @@ public class ActivityPlugin extends Plugin {
* @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message.
*/
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) {
PluginResult result = new PluginResult(PluginResult.Status.OK, "");
try {
if (action.equals("start")) {
this.startActivity(args.getString(0));
callbackContext.sendPluginResult(result);
callbackContext.success();
return true;
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, "JSON Exception");
callbackContext.sendPluginResult(result);
return false;
}
return false;
}
// --------------------------------------------------------------------------
@@ -69,9 +73,9 @@ public class ActivityPlugin extends Plugin {
public void startActivity(String className) {
try {
Intent intent = new Intent().setClass(this.ctx.getActivity(), Class.forName(className));
Intent intent = new Intent().setClass(this.cordova.getActivity(), Class.forName(className));
LOG.d(TAG, "Starting activity %s", className);
this.ctx.getActivity().startActivity(intent);
this.cordova.getActivity().startActivity(intent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
LOG.e(TAG, "Error starting activity %s", className);

View File

@@ -21,14 +21,72 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.util.Purity;
import org.apache.cordova.test.actions.iframe;
import android.app.Activity;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class IFrameTest extends ActivityInstrumentationTestCase2<iframe> {
public class IFrameTest extends ActivityInstrumentationTestCase2 {
public IFrameTest() {
super("org.apache.cordova.test",iframe.class);
}
private Instrumentation mInstr;
private Activity testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
private TouchUtils touch;
private Purity touchTool;
public IFrameTest() {
super("org.apache.cordova.test",iframe.class);
}
protected void setUp() throws Exception {
super.setUp();
mInstr = this.getInstrumentation();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
touch = new TouchUtils();
touchTool = new Purity(testActivity, getInstrumentation());
}
public void testIframeDest()
{
testView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
sleep(3000);
testView.sendJavascript("loadUrl('index2.html')");
sleep(1000);
String url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
public void testIframeHistory()
{
testView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
sleep(3000);
testView.sendJavascript("loadUrl('index2.html')");
sleep(1000);
String url = testView.getUrl();
testView.backHistory();
sleep(1000);
assertTrue(url.endsWith("index.html"));
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -21,15 +21,55 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.util.Purity;
import org.apache.cordova.test.actions.jqmtabbackbutton;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class JQMTabTest extends ActivityInstrumentationTestCase2<jqmtabbackbutton> {
public JQMTabTest(Class<jqmtabbackbutton> activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
private Instrumentation mInstr;
private jqmtabbackbutton testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
private Purity touchTool;
public JQMTabTest()
{
super("org.apache.cordova.test.activity", jqmtabbackbutton.class);
}
protected void setUp() throws Exception {
super.setUp();
mInstr = this.getInstrumentation();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
touchTool = new Purity(testActivity, getInstrumentation());
}
public void testTouch()
{
sleep(5000);
int viewportHeight = touchTool.getViewportHeight() - 40;
int viewportWidth = touchTool.getViewportWidth();
touchTool.touch(50, viewportHeight);
sleep(10000);
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -0,0 +1,171 @@
/*
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.
*/
/*
* Purity is a small set of Android utility methods that allows us to simulate touch events on
* Android applications. This is important for simulating some of the most annoying tests.
*/
package org.apache.cordova.test.util;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Picture;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.webkit.WebView;
public class Purity {
Instrumentation inst;
int width, height;
float density;
Bitmap state;
boolean fingerDown = false;
public Purity(Context ctx, Instrumentation i)
{
inst = i;
DisplayMetrics display = ctx.getResources().getDisplayMetrics();
density = display.density;
width = display.widthPixels;
height = display.heightPixels;
}
/*
* WebKit doesn't give you real pixels anymore, this is done for subpixel fonts to appear on
* iOS and Android. However, Android automation requires real pixels
*/
private int getRealCoord(int coord)
{
return (int) (coord * density);
}
public int getViewportWidth()
{
return (int) (width/density);
}
public int getViewportHeight()
{
return (int) (height/density);
}
public void touch(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
if(!fingerDown)
{
MotionEvent downEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(downEvent);
}
MotionEvent upEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, realX, realY, 0);
inst.sendPointerSync(upEvent);
}
public void touchStart(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = true;
}
//Move from the touch start
public void touchMove(int x, int y)
{
if(!fingerDown)
touchStart(x,y);
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, realX, realY, 0);
inst.sendPointerSync(event);
}
}
public void touchEnd(int x, int y)
{
if(!fingerDown)
{
touch(x, y);
}
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = false;
}
}
public void setBitmap(WebView view)
{
Picture p = view.capturePicture();
state = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
}
public boolean checkRenderView(WebView view)
{
if(state == null)
{
setBitmap(view);
return false;
}
else
{
Picture p = view.capturePicture();
Bitmap newState = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
boolean result = newState.equals(state);
newState.recycle();
return result;
}
}
public void clearBitmap()
{
if(state != null)
state.recycle();
}
protected void finalize()
{
clearBitmap();
}
}