Compare commits

..

15 Commits
4.1.1 ... 4.0.2

Author SHA1 Message Date
Steve Gill
a67bddbd82 Set VERSION to 4.0.2 (via coho) 2015-05-20 13:12:33 -07:00
Steve Gill
81eb8ff1f9 Update JS snapshot to version 4.0.2 (via coho) 2015-05-20 13:12:33 -07:00
Joe Bowser
8de13d9af5 Automated tools fail, and you have to remember all four places where this is set. 2015-05-20 08:54:28 -07:00
Joe Bowser
83118456cc Update the package.json 2015-05-19 10:55:29 -07:00
Joe Bowser
8eaa71d9b7 CB-9042 coho failed to update version, so here we are 2015-05-19 08:24:47 -07:00
Joe Bowser
554b599912 CB9042 - Updating Release Notes 2015-05-19 08:13:08 -07:00
Joe Bowser
82528f3973 Adding tests to confirm that preferences aren't changed by Intents 2015-05-15 14:13:41 -07:00
Joe Bowser
4ca80030ce updating existing test code 2015-05-15 14:13:41 -07:00
Joe Bowser
a102d1d23a Forgot to remove the method that copied over the intent data 2015-05-15 14:13:41 -07:00
Joe Bowser
6e495259b2 Getting around to removing this old Intent code 2015-05-15 14:13:41 -07:00
Steve Gill
6b7eaf2386 Set VERSION to 4.0.1 (via coho) 2015-05-08 15:33:04 -07:00
Steve Gill
1d7c033e52 Update JS snapshot to version 4.0.1 (via coho) 2015-05-08 15:33:03 -07:00
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
33 changed files with 580 additions and 615 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,70 +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) ###

View File

@@ -1 +1 @@
4.1.1
4.0.2

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.2";
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
// 23738581906992092a43ad2e643b1e0c43bba38a
/*
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.2';
// file: src/scripts/require.js
/*jshint -W079 */
@@ -328,7 +328,7 @@ module.exports = cordova;
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
// file: node_modules/cordova-android/cordova-js-src/android/nativeapiprovider.js
define("cordova/android/nativeapiprovider", function(require, exports, module) {
/**
@@ -351,7 +351,7 @@ module.exports = {
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
// file: node_modules/cordova-android/cordova-js-src/android/promptbasednativeapi.js
define("cordova/android/promptbasednativeapi", function(require, exports, module) {
/**
@@ -376,6 +376,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 +861,7 @@ module.exports = channel;
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/exec.js
// file: node_modules/cordova-android/cordova-js-src/exec.js
define("cordova/exec", function(require, exports, module) {
/**
@@ -895,7 +896,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 +1234,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 +1361,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 +1504,7 @@ exports.reset();
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/platform.js
// file: node_modules/cordova-android/cordova-js-src/platform.js
define("cordova/platform", function(require, exports, module) {
module.exports = {
@@ -1577,7 +1580,7 @@ function onMessageFromNative(msg) {
});
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/plugin/android/app.js
// file: node_modules/cordova-android/cordova-js-src/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) {
var exec = require('cordova/exec');
@@ -1673,10 +1676,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 +1864,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 +1906,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 +1928,6 @@ utils.createUUID = function() {
UUIDcreatePart(6);
};
/**
* Extends a child object from a parent object using classical inheritance
* pattern.
@@ -1946,7 +1937,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 +1956,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

@@ -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);
@@ -235,10 +223,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 +297,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

@@ -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.2";
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.2",
"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");