Compare commits

..

16 Commits

Author SHA1 Message Date
Marcel Kinard
fb13ab6de2 update RELEASENOTES with latest commit 2014-09-30 20:59:47 -04:00
Joe Bowser
a272fd1531 CB-7674: Added sleep to avoid null error after most recent change to not break API 2014-09-30 17:58:13 -07:00
Marcel Kinard
90766ae0fa CB-7674 move preference activation back into onCreate()
The preference creation actually needs to be before
super.onCreate(savedInstance) in order to avoid the exception
"requestFeature() must be called before adding content". Also ran into an
issue in the native tests "Whitelist" and "User WebView/Client/Chrome" where
it would throw an exception that the CordovaWebView appView already had
a parent and needed to be removed from that parent before the invocation
to root.addView(appView). So I conditionally remove the wrong parent.
Also made a change to the native tests so the menus test would work.
I also put super.init() back into the template, though invoking it is optional
as loadUrl will call it automatically if needed.
2014-09-30 17:51:21 -07:00
Steven Gill
fcb6cc44f1 updated release notes 2014-09-30 13:10:40 -07:00
Steven Gill
ef4383561e Set VERSION to 3.6.4 (via coho) 2014-09-29 14:59:04 -07:00
Steven Gill
025ca36d3a Update JS snapshot to version 3.6.4 (via coho) 2014-09-29 14:59:04 -07:00
Andrew Grieve
c2bba3f5e3 CB-7634 Detect JAVA_HOME properly on Ubuntu 2014-09-29 10:16:52 -04:00
Andrew Grieve
1c3f7e6f93 CB-7579 Fix run script's ability to use non-arch-specific APKs 2014-09-26 15:04:21 +04:00
Vladimir Kotikov
e65bfa41a5 CB-6511 Fixes build for android when app name contains unicode characters. 2014-09-26 11:59:05 +04:00
Marcel Kinard
e2e38ad2b4 Set VERSION to 3.6.3 (via coho) 2014-09-12 15:50:25 -04:00
Marcel Kinard
caa82b2f26 CB-7383 Bump version to 3.6.1 2014-09-05 14:08:46 -04:00
Steven Gill
5652fdc030 updated releasenotes
(cherry picked from commit 5a82dd5110)
2014-09-05 11:05:33 -04:00
Joe Bowser
7dbc5b0965 CB-7463: Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done. 2014-09-04 10:53:41 -07:00
Joe Bowser
60578f3f0d CB-7463: Looked at the Apache BigTop git, gradle uses C-style comments 2014-09-04 10:53:29 -07:00
Joe Bowser
afdd16a214 CB-7460: Fixing bug with KitKat where the background colour would override the CSS colours on the application 2014-09-03 15:26:16 -07:00
Steven Gill
014327c59a Set VERSION to 3.6.0 (via coho) 2014-08-29 16:34:11 -07:00
22 changed files with 256 additions and 658 deletions

3
.gitignore vendored
View File

@@ -37,6 +37,3 @@ Desktop.ini
# IntelliJ IDEA files
*.iml
.idea
npm-debug.log
/node_modules
/framework/build

View File

@@ -1,5 +0,0 @@
language: android
install: npm install
script:
- npm test
- npm run test-build

View File

@@ -30,6 +30,7 @@
* CB-7463: Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done.
* CB-7463: Looked at the Apache BigTop git, gradle uses C-style comments
* CB-7460: Fixing bug with KitKat where the background colour would override the CSS colours on the application
* CB-7674 Preference activation no longer occurs in CordovaActivity.onCreate()
### 3.6.0 (Sept 2014) ###

View File

@@ -1 +1 @@
3.7.0-dev
3.6.4

View File

@@ -48,21 +48,20 @@ function tryCommand(cmd, errMsg) {
// Get valid target from framework/project.properties
module.exports.get_target = function() {
function extractFromFile(filePath) {
var target = shelljs.grep(/\btarget=/, filePath);
if (!target) {
throw new Error('Could not find android target within: ' + filePath);
}
return target.split('=')[1].trim();
}
if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
}
if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
if(fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
var target = shelljs.grep(/target=android-[\d+]/, path.join(ROOT, 'framework', 'project.properties'));
return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', '');
} else if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
// if no target found, we're probably in a project and project.properties is in ROOT.
return extractFromFile(path.join(ROOT, 'project.properties'));
// this is called on the project itself, and can support Google APIs AND Vanilla Android
var target = shelljs.grep(/target=android-[\d+]/, path.join(ROOT, 'project.properties')) ||
shelljs.grep(/target=Google Inc.:Google APIs:[\d+]/, path.join(ROOT, 'project.properties'));
if(target == "" || !target) {
// Try Google Glass APIs
target = shelljs.grep(/target=Google Inc.:Glass Development Kit Preview:[\d+]/, path.join(ROOT, 'project.properties'));
}
return target.split('=')[1].replace('\n', '').replace('\r', '');
}
throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
}
// Returns a promise. Called only by build and clean commands.
@@ -111,13 +110,10 @@ module.exports.check_java = function() {
}
} else if (isWindows) {
// Try to auto-detect java in the default install paths.
var oldSilent = shelljs.config.silent;
shelljs.config.silent = true;
var firstJdkDir =
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
shelljs.config.silent = oldSilent;
if (firstJdkDir) {
// shelljs always uses / in paths.
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
@@ -130,15 +126,13 @@ module.exports.check_java = function() {
}
}).then(function() {
var msg =
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
if (process.env['JAVA_HOME']) {
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
}
'Failed to run "java -version", make sure your java environment is set up\n' +
'including JDK and JRE.\n' +
'Your JAVA_HOME variable is: ' + process.env['JAVA_HOME'];
return tryCommand('java -version', msg)
.then(function() {
return tryCommand('javac -version', msg);
});
}).then(function() {
msg = 'Failed to run "javac -version", make sure you have a Java JDK (not just a JRE) installed.';
return tryCommand('javac -version', msg)
});
}
@@ -148,32 +142,6 @@ module.exports.check_android = function() {
var androidCmdPath = forgivingWhichSync('android');
var adbInPath = !!forgivingWhichSync('adb');
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
function maybeSetAndroidHome(value) {
if (!hasAndroidHome && fs.existsSync(value)) {
hasAndroidHome = true;
process.env['ANDROID_HOME'] = value;
}
}
if (!hasAndroidHome && !androidCmdPath) {
if (isWindows) {
// Android Studio installer.
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
// Stand-alone installer.
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
} else if (process.platform == 'darwin') {
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
// Stand-alone zip file that user might think to put under /Applications
maybeSetAndroidHome('/Applications/android-sdk-macosx');
maybeSetAndroidHome('/Applications/android-sdk');
}
if (process.env['HOME']) {
// or their HOME directory.
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
}
}
if (hasAndroidHome && !androidCmdPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
}
@@ -198,27 +166,13 @@ module.exports.check_android = function() {
});
};
module.exports.getAbsoluteAndroidCmd = function() {
return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
};
module.exports.check_android_target = function(valid_target) {
// valid_target can look like:
// android-19
// android-L
// Google Inc.:Google APIs:20
// Google Inc.:Glass Development Kit Preview:20
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)
var msg = 'Failed to run "android". Make sure you have the latest Android SDK installed, and that the "android" command (inside the tools/ folder) is added to your PATH.';
return tryCommand('android list targets', msg)
.then(function(output) {
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)');
if (!output.match(valid_target)) {
throw new Error('Please install Android target "' + valid_target + '".\n' +
'Hint: Run "android" from your command-line to open the SDK manager.');
}
});
};

View File

@@ -122,7 +122,7 @@ function copyBuildRules(projectPath) {
shell.cp('-f', path.join(srcDir, 'custom_rules.xml'), projectPath);
shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
shell.cp('-f', path.join(srcDir, 'cordova.gradle'), projectPath);
shell.cp('-f', path.join(srcDir, 'settings.gradle'), projectPath);
}
function copyScripts(projectPath) {
@@ -210,9 +210,11 @@ exports.createProject = function(project_path, package_name, project_name, proje
project_template_dir :
path.join(ROOT, 'bin', 'templates', 'project');
var safe_activity_name = project_name.replace(/\W/g, '');
var package_as_path = package_name.replace(/\./g, path.sep);
var activity_dir = path.join(project_path, 'src', package_as_path);
// safe_activity_name is being hardcoded to avoid issues with unicode app name (https://issues.apache.org/jira/browse/CB-6511)
// TODO: provide option to specify activity name via CLI (proposal: https://issues.apache.org/jira/browse/CB-7231)
var safe_activity_name = "CordovaApp";
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
var target_api = check_reqs.get_target();
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
@@ -226,6 +228,10 @@ exports.createProject = function(project_path, package_name, project_name, proje
return validatePackageName(package_name)
.then(function() {
validateProjectName(project_name);
})
// Check that requirements are met and proper targets are installed
.then(function() {
return check_reqs.run();
}).then(function() {
// Log the given values for the project
console.log('Creating Cordova project for the Android platform:');
@@ -301,7 +307,8 @@ function extractProjectNameFromManifest(projectPath) {
// Returns a promise.
exports.updateProject = function(projectPath, shared) {
var newVersion = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
return Q()
// Check that requirements are met and proper targets are installed
return check_reqs.run()
.then(function() {
var projectName = extractProjectNameFromManifest(projectPath);
var target_api = check_reqs.get_target();

View File

@@ -20,13 +20,13 @@
*/
var shell = require('shelljs'),
exec = require('./exec'),
spawn = require('./spawn'),
Q = require('q'),
path = require('path'),
fs = require('fs'),
ROOT = path.join(__dirname, '..', '..');
var check_reqs = require('./check_reqs');
var exec = require('./exec');
var LOCAL_PROPERTIES_TEMPLATE =
'# This file is automatically generated.\n' +
@@ -53,7 +53,7 @@ function sortFilesByDate(files) {
}).map(function(p) { return p.p; });
}
function findOutputApksHelper(dir, build_type, arch) {
function findOutputApksHelper(dir, build_type) {
var ret = findApks(dir).filter(function(candidate) {
// Need to choose between release and debug .apk.
if (build_type === 'debug') {
@@ -69,15 +69,9 @@ function findOutputApksHelper(dir, build_type, arch) {
return ret;
}
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
ret = ret.filter(function(p) {
return ret.filter(function(p) {
return !!/-x86|-arm/.exec(p) == archSpecific;
});
if (arch) {
ret = ret.filter(function(p) {
return p.indexOf('-' + arch) != -1;
});
}
return ret;
}
function hasCustomRules() {
@@ -169,11 +163,11 @@ var builders = {
findOutputApks: function(build_type) {
var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
return findOutputApksHelper(binDir, build_type, null);
return findOutputApksHelper(binDir, build_type);
}
},
gradle: {
getArgs: function(cmd, arch) {
getArgs: function(cmd) {
var lintSteps;
if (process.env['BUILD_MULTIPLE_APKS']) {
lintSteps = [
@@ -193,19 +187,6 @@ var builders = {
'copyDebugLint'
];
}
if (arch == 'arm' && cmd == 'debug') {
cmd = 'assembleArmv7Debug';
} else if (arch == 'arm' && cmd == 'release') {
cmd = 'assembleArmv7Release';
} else if (arch == 'x86' && cmd == 'debug') {
cmd = 'assembleX86Debug';
} else if (arch == 'x86' && cmd == 'release') {
cmd = 'assembleX86Release';
} else if (cmd == 'debug') {
cmd = 'assembleDebug';
} else if (cmd == 'release') {
cmd = 'assembleRelease';
}
var args = [cmd, '-b', path.join(ROOT, 'build.gradle')];
// 10 seconds -> 6 seconds
args.push('-Dorg.gradle.daemon=true');
@@ -236,36 +217,6 @@ var builders = {
shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
shell.mkdir('-p', path.join(projectPath, 'gradle'));
shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(projectPath, 'gradle'));
// If the gradle distribution URL is set, make sure it points to version 1.12.
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
var distributionUrlRegex = '/^distributionUrl=.*$/';
var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-1.12-all.zip';
var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);
// Update the version of build.gradle in each dependent library.
var pluginBuildGradle = path.join(projectPath, 'cordova', 'lib', 'plugin-build.gradle');
var subProjects = extractSubProjectPaths();
for (var i = 0; i < subProjects.length; ++i) {
shell.cp('-f', pluginBuildGradle, path.join(ROOT, subProjects[i], 'build.gradle'));
}
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' +
'include "' + subProjectsAsGradlePaths.join('"\ninclude "') + '"\n');
// Update dependencies within build.gradle.
var buildGradle = fs.readFileSync(path.join(projectPath, 'build.gradle'), 'utf8');
var depsList = '';
subProjectsAsGradlePaths.forEach(function(p) {
depsList += ' debugCompile project(path: "' + p + '", configuration: "debug")\n';
depsList += ' releaseCompile project(path: "' + p + '", configuration: "release")\n';
});
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
fs.writeFileSync(path.join(projectPath, 'build.gradle'), buildGradle);
});
},
@@ -273,10 +224,10 @@ var builders = {
* Builds the project with gradle.
* Returns a promise.
*/
build: function(build_type, arch) {
build: function(build_type) {
var builder = this;
var wrapper = path.join(ROOT, 'gradlew');
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch);
var args = builder.getArgs('build');
return Q().then(function() {
return spawn(wrapper, args);
});
@@ -291,9 +242,9 @@ var builders = {
});
},
findOutputApks: function(build_type, arch) {
var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
return findOutputApksHelper(binDir, build_type, arch);
findOutputApks: function(build_type) {
var binDir = path.join(ROOT, 'build', 'apk');
return findOutputApksHelper(binDir, build_type);
}
},
@@ -308,20 +259,19 @@ var builders = {
clean: function() {
return Q();
},
findOutputApks: function(build_type, arch) {
return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch)));
findOutputApks: function(build_type) {
return sortFilesByDate(builders.ant.findOutputApks(build_type).concat(builders.gradle.findOutputApks(build_type)));
}
}
};
function parseOpts(options, resolvedTarget) {
function parseOpts(options) {
// Backwards-compatibility: Allow a single string argument
if (typeof options == "string") options = [options];
var ret = {
buildType: 'debug',
buildMethod: process.env['ANDROID_BUILD'] || 'ant',
arch: null
buildMethod: process.env['ANDROID_BUILD'] || 'ant'
};
// Iterate through command line options
@@ -347,12 +297,6 @@ function parseOpts(options, resolvedTarget) {
return Q.reject('Build option \'' + options[i] + '\' not recognized.');
}
}
var multiApk = ret.buildMethod == 'gradle' && process.env['BUILD_MULTIPLE_APKS'];
if (multiApk && !/0|false|no/i.exec(multiApk)) {
ret.arch = resolvedTarget && resolvedTarget.arch;
}
return ret;
}
@@ -375,14 +319,15 @@ module.exports.runClean = function(options) {
* Builds the project with the specifed options
* Returns a promise.
*/
module.exports.run = function(options, optResolvedTarget) {
var opts = parseOpts(options, optResolvedTarget);
module.exports.run = function(options) {
var opts = parseOpts(options);
var builder = builders[opts.buildMethod];
return builder.prepEnv()
.then(function() {
return builder.build(opts.buildType, opts.arch);
return builder.build(opts.buildType);
}).then(function() {
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
var apkPaths = builder.findOutputApks(opts.buildType);
console.log('Built the following apk(s):');
console.log(' ' + apkPaths.join('\n '));
return {

View File

@@ -43,60 +43,48 @@ module.exports.list = function() {
});
}
module.exports.resolveTarget = function(target) {
return this.list()
.then(function(device_list) {
if (!device_list || !device_list.length) {
return Q.reject('ERROR: Failed to deploy to device, no devices found.');
}
// default device
target = target || device_list[0];
if (device_list.indexOf(target) < 0) {
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
}
return build.detectArchitecture(target)
.then(function(arch) {
return { target: target, arch: arch, isEmulator: false };
});
});
};
/*
* Installs a previously built application on the device
* and launches it.
* Returns a promise.
*/
module.exports.install = function(target, buildResults) {
return Q().then(function() {
if (target && typeof target == 'object') {
return target;
}
return module.exports.resolveTarget(target);
}).then(function(resolvedTarget) {
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
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 + '"';
return exec(cmd)
.then(function(output) {
if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output);
var launchName;
return this.list()
.then(function(device_list) {
if (!device_list || !device_list.length)
return Q.reject('ERROR: Failed to deploy to device, no devices found.');
//unlock screen
var cmd = 'adb -s ' + resolvedTarget.target + ' shell input keyevent 82';
// default device
target = target || device_list[0];
if (device_list.indexOf(target) < 0)
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
return build.detectArchitecture(target)
.then(function(arch) {
var apk_path = build.findBestApkForArchitecture(buildResults, arch);
launchName = appinfo.getActivityName();
console.log('Using apk: ' + apk_path);
console.log('Installing app on device...');
var cmd = 'adb -s ' + target + ' install -r "' + apk_path + '"';
return exec(cmd);
}, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); })
.then(function() {
// launch the application
console.log('Launching application...');
var cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd);
}).then(function() {
console.log('LAUNCH SUCCESS');
}, function(err) {
return Q.reject('ERROR: Failed to launch application on device: ' + err);
});
}).then(function(output) {
if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output);
//unlock screen
var cmd = 'adb -s ' + target + ' shell input keyevent 82';
return exec(cmd);
}, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); })
.then(function() {
// launch the application
console.log('Launching application...');
var cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd);
}).then(function() {
console.log('LAUNCH SUCCESS');
}, function(err) {
return Q.reject('ERROR: Failed to launch application on device: ' + err);
});
}

View File

@@ -28,7 +28,6 @@ var shell = require('shelljs'),
ROOT = path.join(__dirname, '..', '..'),
child_process = require('child_process'),
new_emulator = 'cordova_emulator';
var check_reqs = require('./check_reqs');
/**
* Returns a Promise for a list of emulator images in the form of objects
@@ -85,7 +84,7 @@ module.exports.list_images = function() {
* Returns a promise.
*/
module.exports.best_image = function() {
var project_target = check_reqs.get_target().replace('android-', '');
var project_target = this.get_target().replace('android-', '');
return this.list_images()
.then(function(images) {
var closest = 9999;
@@ -121,6 +120,11 @@ module.exports.list_started = function() {
});
}
module.exports.get_target = function() {
var target = shell.grep(/target=android-[\d+]/, path.join(ROOT, 'project.properties'));
return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', '');
}
// Returns a promise.
module.exports.list_targets = function() {
return exec('android list targets')
@@ -152,7 +156,7 @@ module.exports.start = function(emulator_ID) {
.then(function(list) {
started_emulators = list;
num_started = started_emulators.length;
if (!emulator_ID) {
if (typeof emulator_ID === 'undefined') {
return self.list_images()
.then(function(emulator_list) {
if (emulator_list.length > 0) {
@@ -163,11 +167,11 @@ module.exports.start = function(emulator_ID) {
return emulator_ID;
});
} else {
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
return Q.reject('ERROR : No emulator images (avds) found.\n' +
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n');
return Q.reject('ERROR : No emulator images (avds) found, if you would like to create an\n' +
' avd follow the instructions provided here:\n' +
' http://developer.android.com/tools/devices/index.html\n' +
' Or run \'android create avd --name <name> --target <targetID>\'\n' +
' in on the command line.');
}
});
} else {
@@ -273,7 +277,14 @@ module.exports.create_image = function(name, target) {
}
}
module.exports.resolveTarget = function(target) {
/*
* Installs a previously built application on the emulator and launches it.
* If no target is specified, then it picks one.
* If no started emulators are found, error out.
* Returns a promise.
*/
module.exports.install = function(target, buildResults) {
var self = this;
return this.list_started()
.then(function(emulator_list) {
if (emulator_list.length < 1) {
@@ -288,48 +299,30 @@ module.exports.resolveTarget = function(target) {
return build.detectArchitecture(target)
.then(function(arch) {
return {target:target, arch:arch, isEmulator:true};
var apk_path = build.findBestApkForArchitecture(buildResults, arch);
console.log('Installing app on emulator...');
console.log('Using apk: ' + apk_path);
return exec('adb -s ' + target + ' install -r "' + apk_path + '"');
});
});
};
/*
* Installs a previously built application on the emulator and launches it.
* If no target is specified, then it picks one.
* If no started emulators are found, error out.
* Returns a promise.
*/
module.exports.install = function(target, buildResults) {
return Q().then(function() {
if (target && typeof target == 'object') {
return target;
}).then(function(output) {
if (output.match(/Failure/)) {
return Q.reject('Failed to install apk to emulator: ' + output);
}
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);
return exec('adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"')
.then(function(output) {
if (output.match(/Failure/)) {
return Q.reject('Failed to install apk to emulator: ' + output);
}
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');
}).then(function() {
// launch the application
console.log('Launching application...');
var launchName = appinfo.getActivityName();
cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd);
}).then(function(output) {
console.log('LAUNCH SUCCESS');
}, function(err) {
return Q.reject('Failed to launch app on emulator: ' + err);
});
return Q();
}, function(err) {
return Q.reject('Failed to install apk to emulator: ' + err);
}).then(function() {
//unlock screen
return exec('adb -s ' + target + ' shell input keyevent 82');
}).then(function() {
// launch the application
console.log('Launching application...');
var launchName = appinfo.getActivityName();
cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
return exec(cmd);
}).then(function(output) {
console.log('LAUNCH SUCCESS');
}, function(err) {
return Q.reject('Failed to launch app on emulator: ' + err);
});
}

View File

@@ -1,63 +0,0 @@
/* Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
// GENERATED FILE! DO NOT EDIT!
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
}
}
apply plugin: 'android-library'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}
android {
compileSdkVersion cordova.cordovaSdkVersion
buildToolsVersion cordova.cordovaBuildToolsVersion
publishNonDefault true
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
}
if (file('build-extras.gradle').exists()) {
apply from: 'build-extras.gradle'
}

View File

@@ -55,66 +55,73 @@ var path = require('path'),
}
}
return Q()
.then(function() {
if (!install_target) {
return build.run(buildFlags).then(function(buildResults) {
if (install_target == '--device') {
return device.install(null, buildResults);
} else if (install_target == '--emulator') {
return emulator.list_started().then(function(started) {
var p = started && started.length > 0 ? Q() : emulator.start();
return p.then(function() { return emulator.install(null, buildResults); });
});
} else if (install_target) {
var devices, started_emulators, avds;
return device.list()
.then(function(res) {
devices = res;
return emulator.list_started();
}).then(function(res) {
started_emulators = res;
return emulator.list_images();
}).then(function(res) {
avds = res;
if (devices.indexOf(install_target) > -1) {
return device.install(install_target, buildResults);
} else if (started_emulators.indexOf(install_target) > -1) {
return emulator.install(install_target, buildResults);
} else {
// if target emulator isn't started, then start it.
var emulator_ID;
for(avd in avds) {
if(avds[avd].name == install_target) {
return emulator.start(install_target)
.then(function() { emulator.install(emulator_ID, buildResults); });
}
}
return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
}
});
} else {
// no target given, deploy to device if available, otherwise use the emulator.
return device.list()
.then(function(device_list) {
if (device_list.length > 0) {
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
install_target = device_list[0];
return device.install(device_list[0], buildResults);
} else {
console.log('WARNING : No target specified, deploying to emulator');
install_target = '--emulator';
}
});
}
}).then(function() {
if (install_target == '--device') {
return device.resolveTarget(null);
} else if (install_target == '--emulator') {
// Give preference to any already started emulators. Else, start one.
return emulator.list_started()
.then(function(started) {
return started && started.length > 0 ? started[0] : emulator.start();
}).then(function(emulatorId) {
return emulator.resolveTarget(emulatorId);
});
}
// They specified a specific device/emulator ID.
return device.list()
.then(function(devices) {
if (devices.indexOf(install_target) > -1) {
return device.resolveTarget(install_target);
}
return emulator.list_started()
.then(function(started_emulators) {
if (started_emulators.indexOf(install_target) > -1) {
return emulator.resolveTarget(install_target);
}
return emulator.list_images()
.then(function(avds) {
// if target emulator isn't started, then start it.
for (avd in avds) {
if (avds[avd].name == install_target) {
return emulator.start(install_target)
.then(function(emulatorId) {
return emulator.resolveTarget(emulatorId);
return emulator.list_started()
.then(function(emulator_list) {
if (emulator_list.length > 0) {
console.log('WARNING : No target specified, deploying to emulator \'' + emulator_list[0] + '\'.');
return emulator.install(emulator_list[0], buildResults);
} else {
console.log('WARNING : No started emulators found, starting an emulator.');
return emulator.best_image()
.then(function(best_avd) {
if(best_avd) {
return emulator.start(best_avd.name)
.then(function(emulator_ID) {
console.log('WARNING : No target specified, deploying to emulator \'' + emulator_ID + '\'.');
return emulator.install(emulator_ID, buildResults);
});
} else {
return emulator.start();
}
});
}
}
return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
});
});
}
});
});
}).then(function(resolvedTarget) {
return build.run(buildFlags, resolvedTarget).then(function(buildResults) {
if (resolvedTarget.isEmulator) {
return emulator.install(resolvedTarget, buildResults);
}
return device.install(resolvedTarget, buildResults);
});
}
});
}

View File

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

View File

@@ -31,7 +31,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:hardwareAccelerated="true" android:supportsRtl="true">
android:hardwareAccelerated="true">
<activity android:name="__ACTIVITY__"
android:label="@string/activity_name"
android:launchMode="singleTop"

View File

@@ -1,29 +1,5 @@
/*
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.
*/
// GENERATED FILE! DO NOT EDIT!
import java.util.regex.Pattern
import groovy.swing.SwingBuilder
ext.cordova = {}
apply from: 'cordova.gradle', to: ext.cordova
apply plugin: 'android'
buildscript {
@@ -32,16 +8,19 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.0+'
classpath 'com.android.tools.build:gradle:0.10.+'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.12'
}
ext.multiarch=false
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
for (subproject in getProjectList()) {
compile project(subproject)
}
}
android {
sourceSets {
main {
@@ -56,11 +35,11 @@ android {
}
defaultConfig {
versionCode Integer.parseInt(System.env.ANDROID_VERSION_CODE ?: ("" + getVersionCodeFromManifest() + "0"))
versionCode Integer.parseInt("" + getVersionCodeFromManifest() + "0")
}
compileSdkVersion cordova.cordovaSdkVersion
buildToolsVersion cordova.cordovaBuildToolsVersion
compileSdkVersion 19
buildToolsVersion "19.0.0"
if (multiarch || System.env.BUILD_MULTIPLE_APKS) {
productFlavors {
@@ -89,78 +68,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
if (System.env.RELEASE_SIGNING_PROPERTIES_FILE) {
signingConfigs {
release {
// These must be set or Gradle will complain (even if they are overridden).
keyAlias = ""
keyPassword = ""
storeFile = null
storePassword = ""
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
addSigningProps(System.env.RELEASE_SIGNING_PROPERTIES_FILE, signingConfigs.release)
}
if (System.env.DEBUG_SIGNING_PROPERTIES_FILE) {
addSigningProps(System.env.DEBUG_SIGNING_PROPERTIES_FILE, signingConfigs.debug)
}
}
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
// SUB-PROJECT DEPENDENCIES START
// SUB-PROJECT DEPENDENCIES END
}
def promptForPassword(msg) {
if (System.console() == null) {
def ret = null
new SwingBuilder().edt {
dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) {
vbox {
label(text: msg)
def input = passwordField()
button(defaultButton: true, text: 'OK', actionPerformed: {
ret = input.password;
dispose();
})
}
}
}
if (!ret) {
throw new GradleException('User canceled build')
}
return new String(ret)
} else {
return System.console().readPassword('\n' + msg);
}
}
def promptForReleaseKeyPassword() {
if (!System.env.RELEASE_SIGNING_PROPERTIES_FILE) {
return;
}
if (!android.signingConfigs.release.storePassword) {
android.signingConfigs.release.storePassword = promptForPassword('Enter key store password: ')
println('set to:' + android.signingConfigs.release.storePassword)
}
if (!android.signingConfigs.release.keyPassword) {
android.signingConfigs.release.keyPassword = promptForPassword('Enter key password: ');
}
}
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.getAllTasks().each() { task ->
if (task.name == 'validateReleaseSigning') {
promptForReleaseKeyPassword()
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.12'
}
def getVersionCodeFromManifest() {
@@ -171,25 +82,13 @@ def getVersionCodeFromManifest() {
return Integer.parseInt(matcher.group(1))
}
def ensureValueExists(filePath, props, key) {
if (props.get(key) == null) {
throw new GradleException(filePath + ': Missing key required "' + key + '"')
def getProjectList() {
def manifestFile = file("project.properties")
def pattern = Pattern.compile("android.library.reference.(\\d+)\\s*=\\s*(.*)")
def matcher = pattern.matcher(manifestFile.getText())
def projects = []
while (matcher.find()) {
projects.add(":" + matcher.group(2).replace("/",":"))
}
return props.get(key)
}
def addSigningProps(propsFilePath, signingConfig) {
def propsFile = file(propsFilePath)
propsFile.withReader { reader ->
def props = new Properties()
props.load(reader)
signingConfig.keyAlias = ensureValueExists(propsFilePath, props, 'keyAlias')
signingConfig.keyPassword = props.get('keyPassword')
signingConfig.storeFile = RelativePath.parse(true, ensureValueExists(propsFilePath, props, 'storeFile')).getFile(propsFile.getParentFile())
signingConfig.storePassword = props.get('storePassword')
}
}
if (file('build-extras.gradle').exists()) {
apply from: 'build-extras.gradle'
return projects
}

View File

@@ -1,120 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.util.regex.Pattern
String getProjectTarget(String defaultTarget) {
def manifestFile = file("project.properties")
def pattern = Pattern.compile("target\\s*=\\s*(.*)")
def matcher = pattern.matcher(manifestFile.getText())
if (matcher.find()) {
matcher.group(1)
} else {
defaultTarget
}
}
String[] getAvailableBuildTools() {
def buildToolsDir = new File(getAndroidSdkDir(), "build-tools")
buildToolsDir.list()
.findAll { it ==~ /[0-9.]+/ }
.sort { a, b -> compareVersions(b, a) }
}
String latestBuildToolsAvailable(String minBuildToolsVersion) {
def availableBuildToolsVersions
try {
availableBuildToolsVersions = getAvailableBuildTools()
} catch (e) {
println "An exception occurred while trying to find the Android build tools."
throw e
}
if (availableBuildToolsVersions.length > 0) {
def highestBuildToolsVersion = availableBuildToolsVersions[0]
if (compareVersions(highestBuildToolsVersion, minBuildToolsVersion) < 0) {
throw new RuntimeException(
"No usable Android build tools found. Highest installed version is " +
highestBuildToolsVersion + "; minimum version required is " +
minBuildToolsVersion + ".")
}
highestBuildToolsVersion
} else {
throw new RuntimeException(
"No installed build tools found. Please install the Android build tools version " +
minBuildToolsVersion + " or higher.")
}
}
// Return the first non-zero result of subtracting version list elements
// pairwise. If they are all identical, return the difference in length of
// the two lists.
int compareVersionList(Collection aParts, Collection bParts) {
def pairs = ([aParts, bParts]).transpose()
pairs.findResult(aParts.size()-bParts.size()) {it[0] - it[1] != 0 ? it[0] - it[1] : null}
}
// Compare two version strings, such as "19.0.0" and "18.1.1.0". If all matched
// elements are identical, the longer version is the largest by this method.
// Examples:
// "19.0.0" > "19"
// "19.0.1" > "19.0.0"
// "19.1.0" > "19.0.1"
// "19" > "18.999.999"
int compareVersions(String a, String b) {
def aParts = a.tokenize('.').collect {it.toInteger()}
def bParts = b.tokenize('.').collect {it.toInteger()}
compareVersionList(aParts, bParts)
}
String getAndroidSdkDir() {
def rootDir = project.rootDir
def androidSdkDir = null
String envVar = System.getenv("ANDROID_HOME")
def localProperties = new File(rootDir, 'local.properties')
String systemProperty = System.getProperty("android.home")
if (envVar != null) {
androidSdkDir = envVar
} else if (localProperties.exists()) {
Properties properties = new Properties()
localProperties.withInputStream { instr ->
properties.load(instr)
}
def sdkDirProp = properties.getProperty('sdk.dir')
if (sdkDirProp != null) {
androidSdkDir = sdkDirProp
} else {
sdkDirProp = properties.getProperty('android.dir')
if (sdkDirProp != null) {
androidSdkDir = (new File(rootDir, sdkDirProp)).getAbsolutePath()
}
}
}
if (androidSdkDir == null && systemProperty != null) {
androidSdkDir = systemProperty
}
if (androidSdkDir == null) {
throw new RuntimeException(
"Unable to determine Android SDK directory.")
}
androidSdkDir
}
ext.cordovaSdkVersion = System.env.MIN_SDK_VERSION ?: getProjectTarget("android-19")
ext.cordovaBuildToolsVersion = latestBuildToolsAvailable("19.1.0")

View File

@@ -0,0 +1,18 @@
import java.util.regex.Pattern
def getProjectList() {
def manifestFile = file("project.properties")
def pattern = Pattern.compile("android.library.reference.(\\d+)\\s*=\\s*(.*)")
def matcher = pattern.matcher(manifestFile.getText())
def projects = []
while (matcher.find()) {
projects.add(":" + matcher.group(2).replace("/",":"))
}
return projects
}
for (subproject in getProjectList()) {
include subproject
}
include ':'

View File

@@ -19,7 +19,7 @@
under the License.
*/
;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '3.7.0-dev';
var PLATFORM_VERSION_BUILD_LABEL = '3.6.4';
// file: src/scripts/require.js
/*jshint -W079 */

View File

@@ -1,19 +1,20 @@
/* 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
/*
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
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.
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.
*/
@@ -24,25 +25,15 @@ buildscript {
}
dependencies {
// This should be updated with each cordova-android release.
// It can affect things like where the .apk is generated.
// It also dictates what the minimum android build-tools version
// that you need (Set in bin/templates/project/cordova.gradle).
// Make sure the value is the same in all locations:
// * framework/build.gradle
// * bin/templates/project/cordova.gradle
// * bin/templates/cordova/lib/plugin-build.gradle
// * distributionUrl within bin/templates/cordova/lib/build.js.
classpath 'com.android.tools.build:gradle:0.12.+'
classpath 'com.android.tools.build:gradle:0.10.+'
}
}
apply plugin: 'android-library'
android {
compileSdkVersion cordova.cordovaSdkVersion
buildToolsVersion cordova.cordovaBuildToolsVersion
publishNonDefault true
compileSdkVersion 19
buildToolsVersion "19.0.0"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7

View File

@@ -65,9 +65,6 @@ public class CordovaChromeClient extends WebChromeClient {
// the video progress view
private View mVideoProgressView;
//Keep track of last AlertDialog showed
private AlertDialog lastHandledDialog;
// File Chooser
public ValueCallback<Uri> mUploadMessage;
@@ -126,7 +123,7 @@ public class CordovaChromeClient extends WebChromeClient {
return true;
}
});
lastHandledDialog = dlg.show();
dlg.show();
return true;
}
@@ -175,7 +172,7 @@ public class CordovaChromeClient extends WebChromeClient {
return true;
}
});
lastHandledDialog = dlg.show();
dlg.show();
return true;
}
@@ -219,7 +216,7 @@ public class CordovaChromeClient extends WebChromeClient {
res.cancel();
}
});
lastHandledDialog = dlg.show();
dlg.show();
}
return true;
}
@@ -331,11 +328,4 @@ public class CordovaChromeClient extends WebChromeClient {
public ValueCallback<Uri> getValueCallback() {
return this.mUploadMessage;
}
public void destroyLastDialog(){
if(lastHandledDialog != null){
lastHandledDialog.cancel();
}
}
}

View File

@@ -61,7 +61,7 @@ import android.widget.FrameLayout;
public class CordovaWebView extends WebView {
public static final String TAG = "CordovaWebView";
public static final String CORDOVA_VERSION = "3.7.0-dev";
public static final String CORDOVA_VERSION = "3.6.4";
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
@@ -788,9 +788,6 @@ public class CordovaWebView extends WebView {
// Load blank page so that JavaScript onunload is called
this.loadUrl("about:blank");
//Remove last AlertDialog
this.chromeClient.destroyLastDialog();
// Forward to plugins
if (this.pluginManager != null) {

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-android",
"version": "3.7.0-dev",
"version": "3.6.4",
"description": "cordova-android release",
"main": "bin/create",
"repository": {
@@ -13,8 +13,7 @@
"apache"
],
"scripts": {
"test": "jasmine-node --color spec",
"test-build": "rm -rf \"test create\"; ./bin/create \"test create\" com.test.app Test && \"./test create/cordova/build\" && rm -rf \"test create\""
"test": "jasmine-node --color spec"
},
"author": "Apache Software Foundation",
"license": "Apache version 2.0",

View File

@@ -34,7 +34,7 @@ found at https://code.google.com/p/robotium/ and the jar should be put in the
To run manually from command line:
0. Build by entering `ant debug install`
0. Run tests by clicking on "CordovaNativeTests" app icon on the device
0. Run tests by clicking on "CordovaTest" icon on device
To run from Eclipse: