Compare commits

..

3 Commits
4.1.1 ... 4.0.0

Author SHA1 Message Date
Andrew Grieve
f224b1f2d4 CB-8834 Don't fail to install on VERSION_DOWNGRADE 2015-04-09 11:29:18 -04:00
Andrew Grieve
4ac6916dd0 Set VERSION to 4.0.0 (via coho) 2015-04-09 11:05:47 -04:00
Andrew Grieve
a31107e389 Update JS snapshot to version 4.0.0 (via coho) 2015-04-09 11:05:47 -04:00
39 changed files with 669 additions and 675 deletions

View File

@@ -1,4 +0,0 @@
*.properties
bin
gen
proguard-project.txt

View File

@@ -1,8 +1,6 @@
language: android
sudo: false
install:
- npm install
- echo y | android update sdk -u --filter android-22
install: npm install
script:
- npm test
- npm run test-build

45
LICENSE
View File

@@ -1,4 +1,4 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015 Apache Cordova
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -226,9 +226,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
================================================================================
bin/node_modules/shelljs
================================================================================
Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
All rights reserved.
@@ -245,19 +247,19 @@ modification, are permitted provided that the following conditions are met:
names of the contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
bin/node_modules/nopt
bin/node_modules/shelljs
================================================================================
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
All rights reserved.
@@ -283,32 +285,3 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
================================================================================
bin/node_modules/which
================================================================================
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -19,78 +19,6 @@
#
-->
## Release Notes for Cordova (Android) ##
Update these notes using: git log --pretty=format:'* %s' --topo-order --no-merges *remote*/4.1.x...HEAD
### Release 4.1.1 (Aug 2015) ###
* CB-9428 update script now bumps up minSdkVersion to 14 if it is less than that
* CB-9430 Fixes check_reqs failure when javac returns an extra line
### Release 4.1.0 (Jul 2015) ###
* CB-9185 Fixed an issue when unsigned apks couldn't be found. This closes #202
* CB-9397 Fixes minor issues with `cordova requirements android`
* CB-9389 Fixes build/check_reqs hang
* CB-9392 Fixed printing flavored versions. This closes #184.
* CB-9382 [Android] Fix KeepRunning setting when Plugin activity is showed. This closes #200
* CB-9391 Fixes cdvBuildMultipleApks option casting
* CB-9343 Split the Content-Type to obtain a clean mimetype
* CB-9255 Make getUriType case insensitive.
* CB-9149 Fixes JSHint issue introduced by 899daa9
* CB-9372: Remove unused files: 'main.js' & 'master.css'. This closes #198
* CB-9149 Make gradle alias subprojects in order to handle libs that depend on libs. This closes #182
* Update min SDK version to 14
* Update licenses. This closes #190
* CB-9185 Fix signed release build exception. This closes #193.
* CB-9286 Fixes build failure when ANDROID_HOME is not set.
* CB-9284 Fix for handling absolute path for keystore in build.json
* CB-9260 Install Android-22 on Travis-CI
* Adding .ratignore file.
* CB-9119 Adding lib/retry.js for retrying promise-returning functions. Retrying 'adb install' in emulator.js because it sometimes hangs.
* CB-9115 android: Grant Lollipop permission req
* Remove extra console message
* CB-8898 Report expected gradle location properly
* CB-8898 Fixes gradle check failure due to missing quotes
* CB-9080: -d option is not supported on Android 4.1.1 and lower, removing
* CB-8954 Adds `requirements` command support to check_reqs module
* Update JS snapshot to version 4.1.0-dev (via coho)
* CB-8417 updated platform specific files from cordova.js repo
* Adding tests to confirm that preferences aren't changed by Intents
* Forgot to remove the method that copied over the intent data
* Getting around to removing this old Intent code
* Update JS snapshot to version 4.1.0-dev (via coho)
* Fix CordovaPluginTest on KitKat (start-up events seem to change)
* CB-3360 Allow setting a custom User-Agent (close #162)
* CB-8902 Use immersive mode when available when going fullscreen (close #175)
* Make BridgeMode methods public (they were always supposed to be)
* Simplify: EncodingUtils.getBytes(str) -> str.getBytes()
* Don't show warning when gradlew file is read-only
* Don't show warning when prepEnv copies gradlew and it's read-only
* Make gradle wrapper prepEnv code work even when android-sdk is read-only
* CB-8897 Delete drawable/icon.png since it duplicates drawable-mdpi/icon.png
* Updating the template to target mininumSdkTarget=14
* CB-8894: Updating the template to target mininumSdkTarget=14
* CB-8891 Add a note about when the gradle helpers were added
* CB-8891 Add a gradle helper for retrieving config.xml preference values
* CB-8884 Delete Eclipse tweaks from create script
* CB-8834 Don't fail to install on VERSION_DOWNGRADE
* Automated tools fail, and you have to remember all four places where this is set.
* Update the package.json
* CB-9042 coho failed to update version, so here we are
* CB9042 - Updating Release Notes
* Adding tests to confirm that preferences aren't changed by Intents
* updating existing test code
* Forgot to remove the method that copied over the intent data
* Getting around to removing this old Intent code
* CB-8834 Don't fail to install on VERSION_DOWNGRADE
### Release 4.0.2 (May 2015) ###
* Removed Intent Functionality from Preferences - Preferences can no longer be set by intents
### Release 4.0.1 (April 2015) ###
* Bug fixed where platform failed to install on a version downgrade
### Release 4.0.0 (March 2015) ###

View File

@@ -1 +1 @@
4.1.1
4.0.0

View File

@@ -40,13 +40,11 @@ function forgivingWhichSync(cmd) {
}
}
function tryCommand(cmd, errMsg, catchStderr) {
function tryCommand(cmd, errMsg) {
var d = Q.defer();
child_process.exec(cmd, function(err, stdout, stderr) {
if (err) d.reject(new Error(errMsg));
// Sometimes it is necessary to return an stderr instead of stdout in case of success, since
// some commands prints theirs output to stderr instead of stdout. 'javac' is the example
else d.resolve((catchStderr ? stderr : stdout).trim());
else d.resolve(stdout);
});
return d.promise;
}
@@ -72,23 +70,15 @@ module.exports.get_target = function() {
// Returns a promise. Called only by build and clean commands.
module.exports.check_ant = function() {
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
.then(function (output) {
// Parse Ant version from command output
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
});
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.');
};
// Returns a promise. Called only by build and clean commands.
module.exports.check_gradle = function() {
var sdkDir = process.env['ANDROID_HOME'];
if (!sdkDir)
return Q.reject('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.');
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
if (!fs.existsSync(wrapperDir)) {
return Q.reject(new Error('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
return Q.reject(new Error('Could not find gradle wrapper within android sdk. Might need to update your Android SDK.\n' +
'Looked here: ' + wrapperDir));
}
return Q.when();
@@ -106,10 +96,9 @@ module.exports.check_java = function() {
}
} else {
if (javacPath) {
var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
// OS X has a command for finding JAVA_HOME.
if (fs.existsSync('/usr/libexec/java_home')) {
return tryCommand('/usr/libexec/java_home', msg)
return tryCommand('/usr/libexec/java_home', 'Failed to run: /usr/libexec/java_home')
.then(function(stdout) {
process.env['JAVA_HOME'] = stdout.trim();
});
@@ -120,7 +109,7 @@ module.exports.check_java = function() {
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
process.env['JAVA_HOME'] = maybeJavaHome;
} else {
throw new Error(msg);
throw new Error('Could not find JAVA_HOME. Try setting the environment variable manually');
}
}
} else if (isWindows) {
@@ -151,12 +140,7 @@ module.exports.check_java = function() {
}
return tryCommand('java -version', msg)
.then(function() {
// We use tryCommand with catchStderr = true, because
// javac writes version info to stderr instead of stdout
return tryCommand('javac -version', msg, true);
}).then(function (output) {
var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
return match && match[1];
return tryCommand('javac -version', msg);
});
});
};
@@ -212,22 +196,20 @@ module.exports.check_android = function() {
process.env['ANDROID_HOME'] = grandParentDir;
hasAndroidHome = true;
} else {
throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
throw new Error('ANDROID_HOME is not set and no "tools" directory found at ' + parentDir);
}
}
if (hasAndroidHome && !adbInPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
}
if (!process.env['ANDROID_HOME']) {
throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
throw new Error('ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.');
}
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
throw new Error('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
'\nTry update it manually to point to valid SDK directory.');
throw new Error('ANDROID_HOME is set to a non-existant path: ' + process.env['ANDROID_HOME']);
}
// Check that the target sdk level is installed.
return module.exports.check_android_target(module.exports.get_target());
});
};
@@ -241,87 +223,27 @@ module.exports.check_android_target = function(valid_target) {
// android-L
// Google Inc.:Google APIs:20
// Google Inc.:Glass Development Kit Preview:20
if (!valid_target) valid_target = module.exports.get_target();
var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
return tryCommand('android list targets --compact', msg)
.then(function(output) {
var targets = output.split('\n');
if (targets.indexOf(valid_target) >= 0) {
return targets;
if (output.split('\n').indexOf(valid_target) == -1) {
var androidCmd = module.exports.getAbsoluteAndroidCmd();
throw new Error('Please install Android target: "' + valid_target + '".\n\n' +
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
'You will require:\n' +
'1. "SDK Platform" for ' + valid_target + '\n' +
'2. "Android SDK Platform-tools (latest)\n' +
'3. "Android SDK Build-tools" (latest)');
}
var androidCmd = module.exports.getAbsoluteAndroidCmd();
throw new Error('Please install Android target: "' + valid_target + '".\n\n' +
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
'You will require:\n' +
'1. "SDK Platform" for ' + valid_target + '\n' +
'2. "Android SDK Platform-tools (latest)\n' +
'3. "Android SDK Build-tools" (latest)');
});
};
// Returns a promise.
module.exports.run = function() {
return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
return Q.all([this.check_java(), this.check_android()])
.then(function() {
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
});
};
/**
* Object thar represents one of requirements for current platform.
* @param {String} id The unique identifier for this requirements.
* @param {String} name The name of requirements. Human-readable field.
* @param {String} version The version of requirement installed. In some cases could be an array of strings
* (for example, check_android_target returns an array of android targets installed)
* @param {Boolean} installed Indicates whether the requirement is installed or not
*/
var Requirement = function (id, name, version, installed) {
this.id = id;
this.name = name;
this.installed = installed || false;
this.metadata = {
version: version,
};
};
/**
* Methods that runs all checks one by one and returns a result of checks
* as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
*
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
*/
module.exports.check_all = function() {
var requirements = [
new Requirement('java', 'Java JDK'),
new Requirement('androidSdk', 'Android SDK'),
new Requirement('androidTarget', 'Android target'),
new Requirement('gradle', 'Gradle')
];
var checkFns = [
this.check_java,
this.check_android,
this.check_android_target,
this.check_gradle
];
// Then execute requirement checks one-by-one
return checkFns.reduce(function (promise, checkFn, idx) {
// Update each requirement with results
var requirement = requirements[idx];
return promise.then(checkFn)
.then(function (version) {
requirement.installed = true;
requirement.metadata.version = version;
}, function (err) {
requirement.metadata.reason = err instanceof Error ? err.message : err;
});
}, Q())
.then(function () {
// When chain is completed, return requirements array to upstream API
return requirements;
});
};

View File

@@ -58,7 +58,7 @@ function copyJsAndLibrary(projectPath, shared, projectName) {
if (shared) {
shell.rm('-rf', nestedCordovaLibPath);
} else if (!wasSymlink) {
// Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted.
// Delete only the src, since eclipse can't handle its .project file being deleted.
shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
}
});
@@ -72,6 +72,13 @@ function copyJsAndLibrary(projectPath, shared, projectName) {
shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
// Create an eclipse project file and set the name of it to something unique.
// Without this, you can't import multiple CordovaLib projects into the same workspace.
var eclipseProjectFilePath = path.join(nestedCordovaLibPath, '.project');
if (!fs.existsSync(eclipseProjectFilePath)) {
var data = '<?xml version="1.0" encoding="UTF-8"?><projectDescription><name>' + projectName + '-' + 'CordovaLib</name></projectDescription>';
fs.writeFileSync(eclipseProjectFilePath, data, 'utf8');
}
}
}
@@ -128,7 +135,7 @@ function copyScripts(projectPath) {
// Copy in the new ones.
shell.cp('-r', srcScriptsDir, projectPath);
shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir);
shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir);
shell.cp(path.join(ROOT, 'bin', 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
@@ -241,6 +248,17 @@ exports.createProject = function(project_path, package_name, project_name, activ
// Manually create directories that would be empty within the template (since git doesn't track directories).
shell.mkdir(path.join(project_path, 'libs'));
// Add in the proper eclipse project file.
if (use_cli_template) {
var note = 'To show `assets/www` or `res/xml/config.xml`, go to:\n' +
' Project -> Properties -> Resource -> Resource Filters\n' +
'And delete the exclusion filter.\n';
shell.cp(path.join(project_template_dir, 'eclipse-project-CLI'), path.join(project_path, '.project'));
fs.writeFileSync(path.join(project_path, 'assets', '_where-is-www.txt'), note);
} else {
shell.cp(path.join(project_template_dir, 'eclipse-project'), path.join(project_path, '.project'));
}
// copy cordova.js, cordova.jar
copyJsAndLibrary(project_path, use_shared_project, safe_activity_name);
@@ -249,6 +267,7 @@ exports.createProject = function(project_path, package_name, project_name, activ
shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, '.project'));
shell.sed('-i', /__ID__/, package_name, activity_path);
shell.cp('-f', path.join(project_template_dir, 'AndroidManifest.xml'), manifest_path);
@@ -290,31 +309,12 @@ function extractProjectNameFromManifest(projectPath) {
return m[1];
}
// Cordova-android updates sometimes drop support for older versions. Need to update minSDK in existing projects.
function updateMinSDKInManifest(projectPath) {
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
var minSDKVersion = 14;
//grab minSdkVersion from Android.
var m = /android:minSdkVersion\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m) {
throw new Error('Could not find minSDKVersion in ' + manifestPath);
}
//if minSDKVersion in Android.manifest is less than our current min, replace it
if(Number(m[1]) < minSDKVersion) {
console.log('Updating minSdkVersion from ' + m[1] + ' to ' + minSDKVersion + ' in AndroidManifest.xml');
shell.sed('-i', /android:minSdkVersion\s*=\s*"(.*?)"/, 'android:minSdkVersion="'+minSDKVersion+'"', manifestPath);
}
}
// Returns a promise.
exports.updateProject = function(projectPath, shared) {
return Q()
.then(function() {
var projectName = extractProjectNameFromManifest(projectPath);
var target_api = check_reqs.get_target();
updateMinSDKInManifest(projectPath);
copyJsAndLibrary(projectPath, shared, projectName);
copyScripts(projectPath);
copyBuildRules(projectPath);

View File

@@ -82,7 +82,7 @@ function findOutputApksHelper(dir, build_type, arch) {
if (ret.length === 0) {
return ret;
}
// Assume arch-specific build if newest apk has -x86 or -arm.
// Assume arch-specific build if newest api has -x86 or -arm.
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
// And show only arch-specific ones (or non-arch-specific)
ret = ret.filter(function(p) {
@@ -90,12 +90,11 @@ function findOutputApksHelper(dir, build_type, arch) {
return !!/-x86|-arm/.exec(p) == archSpecific;
/*jshint +W018 */
});
if (archSpecific && ret.length > 1) {
if (arch && ret.length > 1) {
ret = ret.filter(function(p) {
return p.indexOf('-' + arch) != -1;
});
}
return ret;
}
@@ -103,19 +102,6 @@ function hasCustomRules() {
return fs.existsSync(path.join(ROOT, 'custom_rules.xml'));
}
function extractRealProjectNameFromManifest(projectPath) {
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m) {
throw new Error('Could not find package name in ' + manifestPath);
}
var packageName=m[1];
var lastDotIndex = packageName.lastIndexOf('.');
return packageName.substring(lastDotIndex + 1);
}
function extractProjectNameFromManifest(projectPath) {
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
@@ -259,28 +245,18 @@ var builders = {
}
}
var name = extractRealProjectNameFromManifest(ROOT);
//Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
var settingsGradlePaths = subProjects.map(function(p){
var realDir=p.replace(/[/\\]/g, ':');
var libName=realDir.replace(name+'-','');
var str='include ":'+libName+'"\n';
if(realDir.indexOf(name+'-')!==-1)
str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
return str;
});
var subProjectsAsGradlePaths = subProjects.map(function(p) { return ':' + p.replace(/[/\\]/g, ':'); });
// Write the settings.gradle file.
fs.writeFileSync(path.join(projectPath, 'settings.gradle'),
'// GENERATED FILE - DO NOT EDIT\n' +
'include ":"\n' + settingsGradlePaths.join(''));
'include ":"\n' +
'include "' + subProjectsAsGradlePaths.join('"\ninclude "') + '"\n');
// Update dependencies within build.gradle.
var buildGradle = fs.readFileSync(path.join(projectPath, 'build.gradle'), 'utf8');
var depsList = '';
subProjects.forEach(function(p) {
var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
depsList += ' debugCompile project(path: "' + libName + '", configuration: "debug")\n';
depsList += ' releaseCompile project(path: "' + libName + '", configuration: "release")\n';
subProjectsAsGradlePaths.forEach(function(p) {
depsList += ' debugCompile project(path: "' + p + '", configuration: "debug")\n';
depsList += ' releaseCompile project(path: "' + p + '", configuration: "release")\n';
});
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
var SYSTEM_LIBRARY_MAPPINGS = [
@@ -329,11 +305,9 @@ var builders = {
var sdkDir = process.env['ANDROID_HOME'];
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
if (process.platform == 'win32') {
shell.rm('-f', path.join(projectPath, 'gradlew.bat'));
shell.cp(path.join(wrapperDir, 'gradlew.bat'), projectPath);
shell.cp('-f', path.join(wrapperDir, 'gradlew.bat'), projectPath);
} else {
shell.rm('-f', path.join(projectPath, 'gradlew'));
shell.cp(path.join(wrapperDir, 'gradlew'), projectPath);
shell.cp('-f', path.join(wrapperDir, 'gradlew'), projectPath);
}
shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
shell.mkdir('-p', path.join(projectPath, 'gradle'));
@@ -345,7 +319,6 @@ var builders = {
var distributionUrlRegex = /distributionUrl.*zip/;
var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.chmod('u+w', gradleWrapperPropertiesPath);
shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
@@ -494,19 +467,16 @@ function parseOpts(options, resolvedTarget) {
// If some values are not specified as command line arguments - use build config to supplement them.
// Command line arguemnts have precedence over build config.
if (buildConfig) {
console.log(path.resolve(buildConfig));
if (!fs.existsSync(buildConfig)) {
throw new Error('Specified build config file does not exist: ' + buildConfig);
}
console.log('Reading build config file: '+ path.resolve(buildConfig));
console.log('Reading build config file: '+ buildConfig);
var config = JSON.parse(fs.readFileSync(buildConfig, 'utf8'));
if (config.android && config.android[ret.buildType]) {
var androidInfo = config.android[ret.buildType];
if(androidInfo.keystore && !packageArgs.keystore) {
if(path.isAbsolute(androidInfo.keystore)) {
packageArgs.keystore = androidInfo.keystore;
} else {
packageArgs.keystore = path.relative(ROOT, path.join(path.dirname(buildConfig), androidInfo.keystore));
}
if(androidInfo.keystore) {
packageArgs.keystore = packageArgs.keystore || path.relative(ROOT, path.join(path.dirname(buildConfig), androidInfo.keystore));
}
['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){

View File

@@ -98,7 +98,7 @@ module.exports.install = function(target, buildResults) {
var launchName = appinfo.getActivityName();
console.log('Using apk: ' + apk_path);
console.log('Installing app on device...');
var cmd = 'adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"';
var cmd = 'adb -s ' + resolvedTarget.target + ' install -r -d "' + apk_path + '"';
return exec(cmd, os.tmpdir())
.then(function(output) {
if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output);

View File

@@ -21,22 +21,14 @@
/* jshint sub:true */
var exec = require('./exec');
var appinfo = require('./appinfo');
var retry = require('./retry');
var build = require('./build');
var exec = require('./exec'),
Q = require('q'),
os = require('os'),
appinfo = require('./appinfo'),
build = require('./build'),
child_process = require('child_process');
var check_reqs = require('./check_reqs');
var Q = require('q');
var os = require('os');
var child_process = require('child_process');
// constants
var ONE_SECOND = 1000; // in milliseconds
var INSTALL_COMMAND_TIMEOUT = 120 * ONE_SECOND; // in milliseconds
var NUM_INSTALL_RETRIES = 3;
var EXEC_KILL_SIGNAL = 'SIGKILL';
/**
* Returns a Promise for a list of emulator images in the form of objects
* {
@@ -306,67 +298,37 @@ module.exports.resolveTarget = function(target) {
* If no started emulators are found, error out.
* Returns a promise.
*/
module.exports.install = function(givenTarget, buildResults) {
var target;
// resolve the target emulator
return Q().then(function () {
if (givenTarget && typeof givenTarget == 'object') {
return givenTarget;
} else {
return module.exports.resolveTarget(givenTarget);
module.exports.install = function(target, buildResults) {
return Q().then(function() {
if (target && typeof target == 'object') {
return target;
}
// set the resolved target
}).then(function (resolvedTarget) {
target = resolvedTarget;
// install the app
}).then(function () {
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
var execOptions = {
timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
killSignal: EXEC_KILL_SIGNAL
};
return module.exports.resolveTarget(target);
}).then(function(resolvedTarget) {
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
console.log('Installing app on emulator...');
console.log('Using apk: ' + apk_path);
var retriedInstall = retry.retryPromise(
NUM_INSTALL_RETRIES,
exec, 'adb -s ' + target.target + ' install -r -d "' + apk_path + '"', os.tmpdir(), execOptions
);
return retriedInstall.then(function (output) {
return exec('adb -s ' + resolvedTarget.target + ' install -r -d "' + apk_path + '"', os.tmpdir())
.then(function(output) {
if (output.match(/Failure/)) {
return Q.reject('Failed to install apk to emulator: ' + output);
} else {
console.log('INSTALL SUCCESS');
}
}, function (err) {
return Q();
}, function(err) {
return Q.reject('Failed to install apk to emulator: ' + err);
}).then(function() {
//unlock screen
return exec('adb -s ' + resolvedTarget.target + ' shell input keyevent 82', os.tmpdir());
}).then(function() {
// launch the application
console.log('Launching application...');
var launchName = appinfo.getActivityName();
var cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd, os.tmpdir());
}).then(function(output) {
console.log('LAUNCH SUCCESS');
}, function(err) {
return Q.reject('Failed to launch app on emulator: ' + err);
});
// unlock screen
}).then(function () {
console.log('Unlocking screen...');
return exec('adb -s ' + target.target + ' shell input keyevent 82', os.tmpdir());
// launch the application
}).then(function () {
console.log('Launching application...');
var launchName = appinfo.getActivityName();
var cmd = 'adb -s ' + target.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd, os.tmpdir());
// report success or failure
}).then(function (output) {
console.log('LAUNCH SUCCESS');
}, function (err) {
return Q.reject('Failed to launch app on emulator: ' + err);
});
};

View File

@@ -19,50 +19,23 @@
under the License.
*/
var child_process = require("child_process");
var Q = require("q");
// constants
var DEFAULT_MAX_BUFFER = 1024000;
var child_process = require('child_process'),
Q = require('q');
// Takes a command and optional current working directory.
// Returns a promise that either resolves with the stdout, or
// rejects with an error message and the stderr.
//
// WARNING:
// opt_cwd is an artifact of an old design, and must
// be removed in the future; the correct solution is
// to pass the options object the same way that
// child_process.exec expects
//
// NOTE:
// exec documented here - https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
module.exports = function(cmd, opt_cwd, options) {
module.exports = function(cmd, opt_cwd) {
var d = Q.defer();
if (typeof options === "undefined") {
options = {};
}
// override cwd to preserve old opt_cwd behavior
options.cwd = opt_cwd;
// set maxBuffer
if (typeof options.maxBuffer === "undefined") {
options.maxBuffer = DEFAULT_MAX_BUFFER;
}
try {
child_process.exec(cmd, options, function(err, stdout, stderr) {
if (err) d.reject("Error executing \"" + cmd + "\": " + stderr);
child_process.exec(cmd, {cwd: opt_cwd, maxBuffer: 1024000}, function(err, stdout, stderr) {
if (err) d.reject('Error executing "' + cmd + '": ' + stderr);
else d.resolve(stdout);
});
} catch(e) {
console.error("error caught: " + e);
console.error('error caught: ' + e);
d.reject(e);
}
return d.promise;
};

View File

@@ -1,66 +0,0 @@
#!/usr/bin/env node
/*
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.
*/
/* jshint node: true */
"use strict";
/*
* Retry a promise-returning function a number of times, propagating its
* results on success or throwing its error on a failed final attempt.
*
* @arg {Number} attemts_left - The number of times to retry the passed call.
* @arg {Function} promiseFunction - A function that returns a promise.
* @arg {...} - Arguments to pass to promiseFunction.
*
* @returns {Promise}
*/
module.exports.retryPromise = function (attemts_left, promiseFunction) {
// NOTE:
// get all trailing arguments, by skipping the first two (attemts_left and
// promiseFunction) because they shouldn't get passed to promiseFunction
var promiseFunctionArguments = Array.prototype.slice.call(arguments, 2);
return promiseFunction.apply(undefined, promiseFunctionArguments).then(
// on success pass results through
function onFulfilled(value) {
return value;
},
// on rejection either retry, or throw the error
function onRejected(error) {
attemts_left -= 1;
if (attemts_left < 1) {
throw error;
}
console.log("A retried call failed. Retrying " + attemts_left + " more time(s).");
// retry call self again with the same arguments, except attemts_left is now lower
var fullArguments = [attemts_left, promiseFunction].concat(promiseFunctionArguments);
return module.exports.retryPromise.apply(undefined, fullArguments);
}
);
};

View File

@@ -20,6 +20,6 @@
*/
// Coho updates this line:
var VERSION = "4.1.1";
var VERSION = "4.0.0";
console.log(VERSION);

View File

@@ -47,5 +47,5 @@
</activity>
</application>
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="__APILEVEL__"/>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="__APILEVEL__"/>
</manifest>

View File

@@ -1,5 +1,5 @@
// Platform: android
// 2c29e187e4206a6a77fba940ef6f77aef5c7eb8c
// b4af1c5ec477dd98cd651932ea6df6d46705d7f9
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,7 +19,7 @@
under the License.
*/
;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '4.1.1';
var PLATFORM_VERSION_BUILD_LABEL = '4.0.0';
// file: src/scripts/require.js
/*jshint -W079 */
@@ -101,15 +101,12 @@ if (typeof module === "object" && typeof require === "function") {
// file: src/cordova.js
define("cordova", function(require, exports, module) {
if(window.cordova){
throw new Error("cordova already defined");
}
if ("cordova" in window) { throw new Error("cordova already defined"); };
var channel = require('cordova/channel');
var platform = require('cordova/platform');
/**
* Intercept calls to addEventListener + removeEventListener and handle deviceready,
* resume, and pause events.
@@ -328,7 +325,7 @@ module.exports = cordova;
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
// file: src/android/android/nativeapiprovider.js
define("cordova/android/nativeapiprovider", function(require, exports, module) {
/**
@@ -351,7 +348,7 @@ module.exports = {
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
// file: src/android/android/promptbasednativeapi.js
define("cordova/android/promptbasednativeapi", function(require, exports, module) {
/**
@@ -376,6 +373,7 @@ module.exports = {
// file: src/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) {
var exec = require('cordova/exec');
var utils = require('cordova/utils');
var moduleExports = module.exports;
@@ -860,7 +858,7 @@ module.exports = channel;
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/exec.js
// file: src/android/exec.js
define("cordova/exec", function(require, exports, module) {
/**
@@ -895,7 +893,11 @@ var cordova = require('cordova'),
// For the ONLINE_EVENT to be viable, it would need to intercept all event
// listeners (both through addEventListener and window.ononline) as well
// as set the navigator property itself.
ONLINE_EVENT: 2
ONLINE_EVENT: 2,
// Uses reflection to access private APIs of the WebView that can send JS
// to be executed.
// Requires Android 3.2.4 or above.
PRIVATE_API: 3
},
jsToNativeBridgeMode, // Set lazily.
nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT,
@@ -1229,7 +1231,6 @@ if (!window.console.warn) {
// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onActivated = cordova.addDocumentEventHandler('activated');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
// Listen for DOMContentLoaded and notify our channel subscribers.
@@ -1357,7 +1358,6 @@ if (!window.console.warn) {
// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onActivated = cordova.addDocumentEventHandler('activated');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
// Listen for DOMContentLoaded and notify our channel subscribers.
@@ -1501,7 +1501,7 @@ exports.reset();
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/platform.js
// file: src/android/platform.js
define("cordova/platform", function(require, exports, module) {
module.exports = {
@@ -1577,7 +1577,7 @@ function onMessageFromNative(msg) {
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/plugin/android/app.js
// file: src/android/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) {
var exec = require('cordova/exec');
@@ -1673,10 +1673,6 @@ module.exports = {
// file: src/common/pluginloader.js
define("cordova/pluginloader", function(require, exports, module) {
/*
NOTE: this file is NOT used when we use the browserify workflow
*/
var modulemapper = require('cordova/modulemapper');
var urlutil = require('cordova/urlutil');
@@ -1865,14 +1861,15 @@ utils.typeName = function(val) {
/**
* Returns an indication of whether the argument is an array or not
*/
utils.isArray = Array.isArray ||
function(a) {return utils.typeName(a) == 'Array';};
utils.isArray = function(a) {
return utils.typeName(a) == 'Array';
};
/**
* Returns an indication of whether the argument is a Date or not
*/
utils.isDate = function(d) {
return (d instanceof Date);
return utils.typeName(d) == 'Date';
};
/**
@@ -1906,24 +1903,16 @@ utils.clone = function(obj) {
* Returns a wrapped version of the function
*/
utils.close = function(context, func, params) {
return function() {
var args = params || arguments;
return func.apply(context, args);
};
};
//------------------------------------------------------------------------------
function UUIDcreatePart(length) {
var uuidpart = "";
for (var i=0; i<length; i++) {
var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
if (uuidchar.length == 1) {
uuidchar = "0" + uuidchar;
}
uuidpart += uuidchar;
if (typeof params == 'undefined') {
return function() {
return func.apply(context, arguments);
};
} else {
return function() {
return func.apply(context, params);
};
}
return uuidpart;
}
};
/**
* Create a UUID
@@ -1936,7 +1925,6 @@ utils.createUUID = function() {
UUIDcreatePart(6);
};
/**
* Extends a child object from a parent object using classical inheritance
* pattern.
@@ -1946,7 +1934,6 @@ utils.extend = (function() {
var F = function() {};
// extend Child from Parent
return function(Child, Parent) {
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.__super__ = Parent.prototype;
@@ -1966,7 +1953,18 @@ utils.alert = function(msg) {
};
//------------------------------------------------------------------------------
function UUIDcreatePart(length) {
var uuidpart = "";
for (var i=0; i<length; i++) {
var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
if (uuidchar.length == 1) {
uuidchar = "0" + uuidchar;
}
uuidpart += uuidchar;
}
return uuidpart;
}
});

View File

@@ -0,0 +1,165 @@
/*
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.
*/
var deviceInfo = function() {
document.getElementById("platform").innerHTML = device.platform;
document.getElementById("version").innerHTML = device.version;
document.getElementById("uuid").innerHTML = device.uuid;
document.getElementById("name").innerHTML = device.name;
document.getElementById("width").innerHTML = screen.width;
document.getElementById("height").innerHTML = screen.height;
document.getElementById("colorDepth").innerHTML = screen.colorDepth;
};
var getLocation = function() {
var suc = function(p) {
alert(p.coords.latitude + " " + p.coords.longitude);
};
var locFail = function() {
};
navigator.geolocation.getCurrentPosition(suc, locFail);
};
var beep = function() {
navigator.notification.beep(2);
};
var vibrate = function() {
navigator.notification.vibrate(0);
};
function roundNumber(num) {
var dec = 3;
var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
return result;
}
var accelerationWatch = null;
function updateAcceleration(a) {
document.getElementById('x').innerHTML = roundNumber(a.x);
document.getElementById('y').innerHTML = roundNumber(a.y);
document.getElementById('z').innerHTML = roundNumber(a.z);
}
var toggleAccel = function() {
if (accelerationWatch !== null) {
navigator.accelerometer.clearWatch(accelerationWatch);
updateAcceleration({
x : "",
y : "",
z : ""
});
accelerationWatch = null;
} else {
var options = {};
options.frequency = 1000;
accelerationWatch = navigator.accelerometer.watchAcceleration(
updateAcceleration, function(ex) {
alert("accel fail (" + ex.name + ": " + ex.message + ")");
}, options);
}
};
var preventBehavior = function(e) {
e.preventDefault();
};
function dump_pic(data) {
var viewport = document.getElementById('viewport');
console.log(data);
viewport.style.display = "";
viewport.style.position = "absolute";
viewport.style.top = "10px";
viewport.style.left = "10px";
document.getElementById("test_img").src = data;
}
function fail(msg) {
alert(msg);
}
function show_pic() {
navigator.camera.getPicture(dump_pic, fail, {
quality : 50
});
}
function close() {
var viewport = document.getElementById('viewport');
viewport.style.position = "relative";
viewport.style.display = "none";
}
function contacts_success(contacts) {
alert(contacts.length
+ ' contacts returned.'
+ (contacts[2] && contacts[2].name ? (' Third contact is ' + contacts[2].name.formatted)
: ''));
}
function get_contacts() {
var obj = new ContactFindOptions();
obj.filter = "";
obj.multiple = true;
navigator.contacts.find(
[ "displayName", "name" ], contacts_success,
fail, obj);
}
function check_network() {
var networkState = navigator.network.connection.type;
var states = {};
states[Connection.UNKNOWN] = 'Unknown connection';
states[Connection.ETHERNET] = 'Ethernet connection';
states[Connection.WIFI] = 'WiFi connection';
states[Connection.CELL_2G] = 'Cell 2G connection';
states[Connection.CELL_3G] = 'Cell 3G connection';
states[Connection.CELL_4G] = 'Cell 4G connection';
states[Connection.NONE] = 'No network connection';
confirm('Connection type:\n ' + states[networkState]);
}
var watchID = null;
function updateHeading(h) {
document.getElementById('h').innerHTML = h.magneticHeading;
}
function toggleCompass() {
if (watchID !== null) {
navigator.compass.clearWatch(watchID);
watchID = null;
updateHeading({ magneticHeading : "Off"});
} else {
var options = { frequency: 1000 };
watchID = navigator.compass.watchHeading(updateHeading, function(e) {
alert('Compass Error: ' + e.code);
}, options);
}
}
function init() {
// the next line makes it impossible to see Contacts on the HTC Evo since it
// doesn't have a scroll button
// document.addEventListener("touchmove", preventBehavior, false);
document.addEventListener("deviceready", deviceInfo, true);
}

View File

@@ -0,0 +1,116 @@
/*
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.
*/
body {
background:#222 none repeat scroll 0 0;
color:#666;
font-family:Helvetica;
font-size:72%;
line-height:1.5em;
margin:0;
border-top:1px solid #393939;
}
#info{
background:#ffa;
border: 1px solid #ffd324;
-webkit-border-radius: 5px;
border-radius: 5px;
clear:both;
margin:15px 6px 0;
width:295px;
padding:4px 0px 2px 10px;
}
#info > h4{
font-size:.95em;
margin:5px 0;
}
#stage.theme{
padding-top:3px;
}
/* Definition List */
#stage.theme > dl{
padding-top:10px;
clear:both;
margin:0;
list-style-type:none;
padding-left:10px;
overflow:auto;
}
#stage.theme > dl > dt{
font-weight:bold;
float:left;
margin-left:5px;
}
#stage.theme > dl > dd{
width:45px;
float:left;
color:#a87;
font-weight:bold;
}
/* Content Styling */
#stage.theme > h1, #stage.theme > h2, #stage.theme > p{
margin:1em 0 .5em 13px;
}
#stage.theme > h1{
color:#eee;
font-size:1.6em;
text-align:center;
margin:0;
margin-top:15px;
padding:0;
}
#stage.theme > h2{
clear:both;
margin:0;
padding:3px;
font-size:1em;
text-align:center;
}
/* Stage Buttons */
#stage.theme a.btn{
border: 1px solid #555;
-webkit-border-radius: 5px;
border-radius: 5px;
text-align:center;
display:block;
float:left;
background:#444;
width:150px;
color:#9ab;
font-size:1.1em;
text-decoration:none;
padding:1.2em 0;
margin:3px 0px 3px 5px;
}
#stage.theme a.btn.large{
width:308px;
padding:1.2em 0;
}

View File

@@ -118,7 +118,7 @@ if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.propert
}
// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvBuildMultipleApks = !!cdvBuildMultipleApks;
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
@@ -152,8 +152,11 @@ task cdvPrintProps << {
println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
println('cdvBuildArch=' + cdvBuildArch)
println('computedVersionCode=' + android.defaultConfig.versionCode)
android.productFlavors.each { flavor ->
println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
if (android.productFlavors.has('armv7')) {
println('computedArmv7VersionCode=' + android.productFlavors.armv7.versionCode)
}
if (android.productFlavors.has('x86')) {
println('computedx86VersionCode=' + android.productFlavors.x86.versionCode)
}
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>__NAME__</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<filteredResources>
<filter>
<id>1388696068187</id>
<name></name>
<type>10</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-true-CordovaLib|platform_www|cordova</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>__NAME__</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<linkedResources>
<link>
<name>config.xml</name>
<type>1</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/config.xml</locationURI>
</link>
<link>
<name>www</name>
<type>2</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/www</locationURI>
</link>
<link>
<name>merges</name>
<type>2</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/merges</locationURI>
</link>
</linkedResources>
<filteredResources>
<filter>
<id>1390880034107</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-projectRelativePath-matches-false-true-^(build.xml|ant-gen|ant-build|custom_rules.xml|CordovaLib|platform_www|cordova)</arguments>
</matcher>
</filter>
<filter>
<id>1390880034108</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-projectRelativePath-matches-false-true-^(assets/www|res/xml/config.xml)</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -51,7 +51,11 @@ var cordova = require('cordova'),
// For the ONLINE_EVENT to be viable, it would need to intercept all event
// listeners (both through addEventListener and window.ononline) as well
// as set the navigator property itself.
ONLINE_EVENT: 2
ONLINE_EVENT: 2,
// Uses reflection to access private APIs of the WebView that can send JS
// to be executed.
// Requires Android 3.2.4 or above.
PRIVATE_API: 3
},
jsToNativeBridgeMode, // Set lazily.
nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT,

View File

@@ -19,5 +19,5 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
<uses-sdk android:minSdkVersion="14" />
<uses-sdk android:minSdkVersion="10" />
</manifest>

View File

@@ -152,26 +152,6 @@ def doPromptForPassword(msg) {
}
}
def doGetConfigXml() {
def xml = file("res/xml/config.xml").getText()
// Disable namespace awareness since Cordova doesn't use them properly
return new XmlParser(false, false).parseText(xml)
}
def doGetConfigPreference(name, defaultValue) {
name = name.toLowerCase()
def root = doGetConfigXml()
def ret = defaultValue
root.preference.each { it ->
def attrName = it.attribute("name")
if (attrName && attrName.toLowerCase() == name) {
ret = it.attribute("value")
}
}
return ret
}
// Properties exported here are visible to all plugins.
ext {
// These helpers are shared, but are not guaranteed to be stable / unchanged.
@@ -181,12 +161,5 @@ ext {
privateHelpers.extractIntFromManifest = { name -> doExtractIntFromManifest(name) }
privateHelpers.promptForPassword = { msg -> doPromptForPassword(msg) }
privateHelpers.ensureValueExists = { filePath, props, key -> doEnsureValueExists(filePath, props, key) }
// These helpers can be used by plugins / projects and will not change.
cdvHelpers = {}
// Returns a XmlParser for the config.xml. Added in 4.1.0.
cdvHelpers.getConfigXml = { doGetConfigXml() }
// Returns the value for the desired <preference>. Added in 4.1.0.
cdvHelpers.getConfigPreference = { name, defaultValue -> doGetConfigPreference(name, defaultValue) }
}

View File

@@ -36,8 +36,8 @@ public class Config {
public static void init(Activity action) {
parser = new ConfigXmlParser();
parser.parse(action);
//TODO: Add feature to bring this back. Some preferences should be overridden by intents, but not all
parser.getPreferences().setPreferencesBundle(action.getIntent().getExtras());
parser.getPreferences().copyIntoIntentExtras(action);
}
// Intended to be used for testing only; creates an empty configuration.

View File

@@ -31,7 +31,6 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -89,9 +88,6 @@ public class CordovaActivity extends Activity {
// when another application (activity) is started.
protected boolean keepRunning = true;
// Flag to keep immersive mode if set to fullscreen
protected boolean immersiveMode;
// Read from config.xml:
protected CordovaPreferences preferences;
protected String launchUrl;
@@ -112,23 +108,15 @@ public class CordovaActivity extends Activity {
{
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
}
if(preferences.getBoolean("SetFullscreen", false))
{
Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
preferences.set("Fullscreen", true);
}
if(preferences.getBoolean("Fullscreen", false))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
immersiveMode = true;
}
else
{
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else if (preferences.getBoolean("Fullscreen", false)) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
@@ -164,6 +152,7 @@ public class CordovaActivity extends Activity {
parser.parse(this);
preferences = parser.getPreferences();
preferences.setPreferencesBundle(getIntent().getExtras());
preferences.copyIntoIntentExtras(this);
launchUrl = parser.getLaunchUrl();
pluginEntries = parser.getPluginEntries();
Config.parser = parser;
@@ -235,10 +224,7 @@ public class CordovaActivity extends Activity {
LOG.d(TAG, "Paused the activity.");
if (this.appView != null) {
// CB-9382 If there is an activity that started for result and main activity is waiting for callback
// result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
this.appView.handlePause(keepRunning);
this.appView.handlePause(this.keepRunning);
}
}
@@ -312,24 +298,6 @@ public class CordovaActivity extends Activity {
}
}
/**
* Called when view focus is changed
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && immersiveMode) {
final int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
getWindow().getDecorView().setSystemUiVisibility(uiOptions);
}
}
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
// Capture requestCode here so that it is captured in the setActivityResultCallback() case.

View File

@@ -61,6 +61,13 @@ public class CordovaPreferences {
String value = prefs.get(name);
if (value != null) {
return Boolean.parseBoolean(value);
} else if (preferencesBundleExtras != null) {
Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue instanceof String) {
return "true".equals(bundleValue);
}
// Gives a nice warning if type is wrong.
return preferencesBundleExtras.getBoolean(name, defaultValue);
}
return defaultValue;
}
@@ -76,6 +83,13 @@ public class CordovaPreferences {
if (value != null) {
// Use Integer.decode() can't handle it if the highest bit is set.
return (int)(long)Long.decode(value);
} else if (preferencesBundleExtras != null) {
Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue instanceof String) {
return Integer.valueOf((String)bundleValue);
}
// Gives a nice warning if type is wrong.
return preferencesBundleExtras.getInt(name, defaultValue);
}
return defaultValue;
}
@@ -85,6 +99,13 @@ public class CordovaPreferences {
String value = prefs.get(name);
if (value != null) {
return Double.valueOf(value);
} else if (preferencesBundleExtras != null) {
Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue instanceof String) {
return Double.valueOf((String)bundleValue);
}
// Gives a nice warning if type is wrong.
return preferencesBundleExtras.getDouble(name, defaultValue);
}
return defaultValue;
}
@@ -94,8 +115,69 @@ public class CordovaPreferences {
String value = prefs.get(name);
if (value != null) {
return value;
} else if (preferencesBundleExtras != null && !"errorurl".equals(name)) {
Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue != null) {
return bundleValue.toString();
}
}
return defaultValue;
}
// Plugins should not rely on values within the intent since this does not work
// for apps with multiple webviews. Instead, they should retrieve prefs from the
// Config object associated with their webview.
public void copyIntoIntentExtras(Activity action) {
for (String name : prefs.keySet()) {
String value = prefs.get(name);
if (value == null) {
continue;
}
if (name.equals("loglevel")) {
LOG.setLogLevel(value);
} else if (name.equals("splashscreen")) {
// Note: We should probably pass in the classname for the variable splash on splashscreen!
int resource = action.getResources().getIdentifier(value, "drawable", action.getClass().getPackage().getName());
if(resource == 0) {
resource = action.getResources().getIdentifier(value, "drawable", action.getPackageName());
}
action.getIntent().putExtra(name, resource);
}
else if(name.equals("backgroundcolor")) {
int asInt = (int)(long)Long.decode(value);
action.getIntent().putExtra(name, asInt);
}
else if(name.equals("loadurltimeoutvalue")) {
int asInt = Integer.decode(value);
action.getIntent().putExtra(name, asInt);
}
else if(name.equals("splashscreendelay")) {
int asInt = Integer.decode(value);
action.getIntent().putExtra(name, asInt);
}
else if(name.equals("keeprunning"))
{
boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool);
}
else if(name.equals("inappbrowserstorageenabled"))
{
boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool);
}
else if(name.equals("disallowoverscroll"))
{
boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool);
}
else
{
action.getIntent().putExtra(name, value);
}
}
// In the normal case, the intent extras are null until the first call to putExtra().
if (preferencesBundleExtras == null) {
preferencesBundleExtras = action.getIntent().getExtras();
}
}
}

View File

@@ -28,6 +28,8 @@ import android.os.Looper;
import android.util.Base64;
import android.webkit.MimeTypeMap;
import org.apache.http.util.EncodingUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -36,7 +38,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.FileChannel;
@@ -104,28 +105,28 @@ public class CordovaResourceApi {
public static int getUriType(Uri uri) {
assertNonRelative(uri);
String scheme = uri.getScheme();
if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
return URI_TYPE_CONTENT;
}
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equalsIgnoreCase(scheme)) {
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
return URI_TYPE_RESOURCE;
}
if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
if (ContentResolver.SCHEME_FILE.equals(scheme)) {
if (uri.getPath().startsWith("/android_asset/")) {
return URI_TYPE_ASSET;
}
return URI_TYPE_FILE;
}
if ("data".equalsIgnoreCase(scheme)) {
if ("data".equals(scheme)) {
return URI_TYPE_DATA;
}
if ("http".equalsIgnoreCase(scheme)) {
if ("http".equals(scheme)) {
return URI_TYPE_HTTP;
}
if ("https".equalsIgnoreCase(scheme)) {
if ("https".equals(scheme)) {
return URI_TYPE_HTTPS;
}
if (PLUGIN_URI_SCHEME.equalsIgnoreCase(scheme)) {
if (PLUGIN_URI_SCHEME.equals(scheme)) {
return URI_TYPE_PLUGIN;
}
return URI_TYPE_UNKNOWN;
@@ -188,11 +189,7 @@ public class CordovaResourceApi {
HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
conn.setDoInput(false);
conn.setRequestMethod("HEAD");
String mimeType = conn.getHeaderField("Content-Type");
if (mimeType != null) {
mimeType = mimeType.split(";")[0];
}
return mimeType;
return conn.getHeaderField("Content-Type");
} catch (IOException e) {
}
}
@@ -287,9 +284,6 @@ public class CordovaResourceApi {
HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
conn.setDoInput(true);
String mimeType = conn.getHeaderField("Content-Type");
if (mimeType != null) {
mimeType = mimeType.split(";")[0];
}
int length = conn.getContentLength();
InputStream inputStream = conn.getInputStream();
return new OpenForReadResult(uri, inputStream, mimeType, length, null);
@@ -433,16 +427,7 @@ public class CordovaResourceApi {
}
}
String dataPartAsString = uriAsString.substring(commaPos + 1);
byte[] data;
if (base64) {
data = Base64.decode(dataPartAsString, Base64.DEFAULT);
} else {
try {
data = dataPartAsString.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
data = dataPartAsString.getBytes();
}
}
byte[] data = base64 ? Base64.decode(dataPartAsString, Base64.DEFAULT) : EncodingUtils.getBytes(dataPartAsString, "UTF-8");
InputStream inputStream = new ByteArrayInputStream(data);
return new OpenForReadResult(uri, inputStream, contentType, data.length, null);
}

View File

@@ -31,7 +31,7 @@ import android.webkit.WebChromeClient.CustomViewCallback;
* are not expected to implement it.
*/
public interface CordovaWebView {
public static final String CORDOVA_VERSION = "4.1.1";
public static final String CORDOVA_VERSION = "4.0.0";
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);

View File

@@ -270,9 +270,9 @@ public class NativeToJsMessageQueue {
}
public static abstract class BridgeMode {
public abstract void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue);
public void notifyOfFlush(NativeToJsMessageQueue queue, boolean fromOnlineEvent) {}
public void reset() {}
abstract void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue);
void notifyOfFlush(NativeToJsMessageQueue queue, boolean fromOnlineEvent) {}
void reset() {}
}
/** Uses JS polls for messages on a timer.. */

View File

@@ -18,7 +18,6 @@
*/
package org.apache.cordova.engine;
import java.util.Arrays;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
@@ -37,7 +36,6 @@ import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.PermissionRequest;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
@@ -268,13 +266,6 @@ public class SystemWebChromeClient extends WebChromeClient {
return true;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onPermissionRequest(final PermissionRequest request) {
Log.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources()));
request.grant(request.getResources());
}
public void destroyLastDialog(){
dialogsHelper.destroyLastDialog();
}

View File

@@ -60,7 +60,6 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
protected final SystemWebView webView;
protected final SystemCookieManager cookieManager;
protected CordovaPreferences preferences;
protected CordovaBridge bridge;
protected CordovaWebViewEngine.Client client;
protected CordovaWebView parentWebView;
@@ -72,15 +71,10 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
/** Used when created via reflection. */
public SystemWebViewEngine(Context context, CordovaPreferences preferences) {
this(new SystemWebView(context), preferences);
this(new SystemWebView(context));
}
public SystemWebViewEngine(SystemWebView webView) {
this(webView, null);
}
public SystemWebViewEngine(SystemWebView webView, CordovaPreferences preferences) {
this.preferences = preferences;
this.webView = webView;
cookieManager = new SystemCookieManager(webView);
}
@@ -92,10 +86,6 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
if (this.cordova != null) {
throw new IllegalStateException();
}
// Needed when prefs are not passed by the constructor
if (preferences == null) {
preferences = parentWebView.getPreferences();
}
this.parentWebView = parentWebView;
this.cordova = cordova;
this.client = client;
@@ -209,19 +199,7 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
// Fix for CB-1405
// Google issue 4641
String defaultUserAgent = settings.getUserAgentString();
// Fix for CB-3360
String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
if (overrideUserAgent != null) {
settings.setUserAgentString(overrideUserAgent);
} else {
String appendUserAgent = preferences.getString("AppendUserAgent", null);
if (appendUserAgent != null) {
settings.setUserAgentString(defaultUserAgent + " " + appendUserAgent);
}
}
// End CB-3360
settings.getUserAgentString();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-android",
"version": "4.1.1",
"version": "4.0.0",
"description": "cordova-android release",
"main": "bin/create",
"repository": {

View File

@@ -45,7 +45,7 @@
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19"/>
<instrumentation
android:name="android.test.InstrumentationTestRunner"

View File

@@ -57,6 +57,8 @@ public class CordovaPluginTest extends BaseCordovaIntegrationTest {
//TODO: add coverage for both cases where onStart is called in CordovaWebViewImpl (handleOnStart and init)
//currently only one of the cases is covered
LifeCyclePlugin testPlugin = (LifeCyclePlugin)cordovaWebView.getPluginManager().getPlugin("LifeCycle");
assertEquals("start,resume,pause,stop,", testPlugin.calls);
testPlugin.calls = "";
// testOnStart
invokeBlockingCallToLifeCycleEvent("callActivityOnStart");

View File

@@ -24,7 +24,7 @@ package org.apache.cordova.test;
public class ErrorUrlTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/htmlnotfound/index.html";
private static final String ERROR_URL = "file:///android_asset/www/htmlnotfound/error.html";
private static final String INVALID_URL = "file:///android_asset/www/invalid.html";
private static final String INVALID_URL = "file:///android_asset/www/index.html";
protected void setUp() throws Exception {
super.setUp();

View File

@@ -31,9 +31,10 @@ public class HtmlNotFoundTest extends BaseCordovaIntegrationTest {
public void testUrl() throws Throwable
{
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
// TODO: Should this be null? Or some other way to indicate it didn't actually load?
runTestOnUiThread(new Runnable() {
public void run() {
assertFalse(START_URL.equals(testActivity.getCordovaWebView().getUrl()));
assertEquals(START_URL, testActivity.getCordovaWebView().getUrl());
}
});
}

View File

@@ -1,44 +0,0 @@
package org.apache.cordova.test;
/*
*
* 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.
*
*/
import android.graphics.Color;
import org.apache.cordova.CordovaPreferences;
public class IntentPreferenceTest extends BaseCordovaIntegrationTest {
private static final String GREEN = Integer.toHexString(Color.GREEN);
private static final String START_URL = "file:///android_asset/www/index.html";
CordovaPreferences prefs;
protected void setUp() throws Exception {
super.setUp();
// INVALID_URL tests that errorUrl and url are *not* settable via the intent.
setUpWithStartUrl(START_URL, "backgroundcolor", GREEN);
prefs = cordovaWebView.getPreferences();
}
public void testUrl() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
assertFalse(prefs.getInteger("backgroundcolor", Color.BLACK) == Color.GREEN);
}
}

View File

@@ -36,7 +36,7 @@ public class MainTestActivity extends BaseTestCordovaActivity {
@Override protected void loadConfig() {
super.loadConfig();
// Need to set this explicitly in prefs since it's not settable via bundle extras.
// Need to set this explicitly in prefs since it's not settable via bundle extras (for security reasons).
String errorUrl = getIntent().getStringExtra("testErrorUrl");
if (errorUrl != null) {
preferences.set("errorUrl", errorUrl);