mirror of
https://github.com/apache/cordova-android.git
synced 2026-05-30 00:00:04 +08:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6201a6f6ec | |||
| fc63f66e89 | |||
| 832e626573 | |||
| ce5d9a2ee8 | |||
| 77c51d3ae7 | |||
| 53dae45430 | |||
| 16343ffe70 | |||
| b37498d5f6 | |||
| 9f41906895 | |||
| fbeb379f1b | |||
| 2dcd50c11b | |||
| 30681eb772 | |||
| 52e575e1e7 | |||
| 890e12c306 | |||
| 6cbf6b7875 | |||
| c255a84941 | |||
| ce7d6d69d9 | |||
| d5538b7076 | |||
| cdfa13b265 | |||
| e31c911c30 | |||
| a658ea1573 | |||
| a986e72338 | |||
| 162d9b6c2e | |||
| 9e3ccf4b3e | |||
| 6b71c2f392 | |||
| 0d313a3964 | |||
| ddac192c4a | |||
| 69a03c2e16 | |||
| 2b128b85f7 | |||
| 879da03438 | |||
| 3f83fdbfc1 | |||
| 949152532c | |||
| 7ce46ed60c | |||
| cb442364ca | |||
| ac34bf1e54 | |||
| a5d300c6ff | |||
| 533677df8b | |||
| 25be42d385 | |||
| 00f6d30e08 | |||
| 090822eb41 | |||
| d9900a725d | |||
| 5cb01f2ae9 | |||
| 4be92f285a | |||
| f9b89e98c2 | |||
| f221441877 | |||
| f2e8c00f49 | |||
| 525ce0e0ad | |||
| 2f7ffa3636 | |||
| 9ae3d2c074 | |||
| bf13fd48ce | |||
| 3b99760a42 | |||
| 0e78dc35d8 | |||
| c8bbdb23de | |||
| 7ee8117186 | |||
| 8237c41143 | |||
| d52ca93ba6 | |||
| 8354651059 | |||
| 81cc3c260f | |||
| 4dc32e194b | |||
| 5a82dd5110 | |||
| f20708a5e7 | |||
| 91cf78f183 |
@@ -37,3 +37,6 @@ Desktop.ini
|
|||||||
# IntelliJ IDEA files
|
# IntelliJ IDEA files
|
||||||
*.iml
|
*.iml
|
||||||
.idea
|
.idea
|
||||||
|
npm-debug.log
|
||||||
|
/node_modules
|
||||||
|
/framework/build
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
language: android
|
||||||
|
install: npm install
|
||||||
|
script:
|
||||||
|
- npm test
|
||||||
|
- npm run test-build
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
* CB-7463: Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done.
|
* 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-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-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) ###
|
### 3.6.0 (Sept 2014) ###
|
||||||
|
|
||||||
|
|||||||
+77
-25
@@ -31,7 +31,7 @@ var isWindows = process.platform == 'win32';
|
|||||||
|
|
||||||
function forgivingWhichSync(cmd) {
|
function forgivingWhichSync(cmd) {
|
||||||
try {
|
try {
|
||||||
return which.sync(cmd);
|
return fs.realpathSync(which.sync(cmd));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -48,20 +48,21 @@ function tryCommand(cmd, errMsg) {
|
|||||||
|
|
||||||
// Get valid target from framework/project.properties
|
// Get valid target from framework/project.properties
|
||||||
module.exports.get_target = function() {
|
module.exports.get_target = function() {
|
||||||
if(fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
|
function extractFromFile(filePath) {
|
||||||
var target = shelljs.grep(/target=android-[\d+]/, path.join(ROOT, 'framework', 'project.properties'));
|
var target = shelljs.grep(/\btarget=/, filePath);
|
||||||
return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', '');
|
if (!target) {
|
||||||
} else if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
|
throw new Error('Could not find android target within: ' + filePath);
|
||||||
// if no target found, we're probably in a project and project.properties is in ROOT.
|
|
||||||
// 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', '');
|
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 no target found, we're probably in a project and project.properties is in ROOT.
|
||||||
|
return extractFromFile(path.join(ROOT, 'project.properties'));
|
||||||
|
}
|
||||||
|
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.
|
// Returns a promise. Called only by build and clean commands.
|
||||||
@@ -101,7 +102,7 @@ module.exports.check_java = function() {
|
|||||||
} else {
|
} else {
|
||||||
// See if we can derive it from javac's location.
|
// See if we can derive it from javac's location.
|
||||||
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
||||||
var maybeJavaHome = path.dirname(path.dirname(fs.realpathSync(javacPath)));
|
var maybeJavaHome = path.dirname(path.dirname(javacPath));
|
||||||
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
||||||
process.env['JAVA_HOME'] = maybeJavaHome;
|
process.env['JAVA_HOME'] = maybeJavaHome;
|
||||||
} else {
|
} else {
|
||||||
@@ -110,10 +111,13 @@ module.exports.check_java = function() {
|
|||||||
}
|
}
|
||||||
} else if (isWindows) {
|
} else if (isWindows) {
|
||||||
// Try to auto-detect java in the default install paths.
|
// Try to auto-detect java in the default install paths.
|
||||||
|
var oldSilent = shelljs.config.silent;
|
||||||
|
shelljs.config.silent = true;
|
||||||
var firstJdkDir =
|
var firstJdkDir =
|
||||||
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
|
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
|
||||||
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
|
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
|
||||||
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
|
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
|
||||||
|
shelljs.config.silent = oldSilent;
|
||||||
if (firstJdkDir) {
|
if (firstJdkDir) {
|
||||||
// shelljs always uses / in paths.
|
// shelljs always uses / in paths.
|
||||||
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
||||||
@@ -126,13 +130,15 @@ module.exports.check_java = function() {
|
|||||||
}
|
}
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
var msg =
|
var msg =
|
||||||
'Failed to run "java -version", make sure your java environment is set up\n' +
|
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
|
||||||
'including JDK and JRE.\n' +
|
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
|
||||||
'Your JAVA_HOME variable is: ' + process.env['JAVA_HOME'];
|
if (process.env['JAVA_HOME']) {
|
||||||
|
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
|
||||||
|
}
|
||||||
return tryCommand('java -version', msg)
|
return tryCommand('java -version', msg)
|
||||||
}).then(function() {
|
.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);
|
||||||
return tryCommand('javac -version', msg)
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,14 +148,46 @@ module.exports.check_android = function() {
|
|||||||
var androidCmdPath = forgivingWhichSync('android');
|
var androidCmdPath = forgivingWhichSync('android');
|
||||||
var adbInPath = !!forgivingWhichSync('adb');
|
var adbInPath = !!forgivingWhichSync('adb');
|
||||||
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
|
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) {
|
if (hasAndroidHome && !androidCmdPath) {
|
||||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
|
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
|
||||||
}
|
}
|
||||||
if (androidCmdPath && !hasAndroidHome) {
|
if (androidCmdPath && !hasAndroidHome) {
|
||||||
var parentDir = path.dirname(androidCmdPath);
|
var parentDir = path.dirname(androidCmdPath);
|
||||||
|
var grandParentDir = path.dirname(parentDir);
|
||||||
if (path.basename(parentDir) == 'tools') {
|
if (path.basename(parentDir) == 'tools') {
|
||||||
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
||||||
hasAndroidHome = true;
|
hasAndroidHome = true;
|
||||||
|
} else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||||
|
process.env['ANDROID_HOME'] = grandParentDir;
|
||||||
|
hasAndroidHome = true;
|
||||||
|
} else {
|
||||||
|
throw new Error('ANDROID_HOME is not set and no "tools" directory found at ' + parentDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasAndroidHome && !adbInPath) {
|
if (hasAndroidHome && !adbInPath) {
|
||||||
@@ -166,13 +204,27 @@ module.exports.check_android = function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.getAbsoluteAndroidCmd = function() {
|
||||||
|
return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
|
||||||
|
};
|
||||||
|
|
||||||
module.exports.check_android_target = function(valid_target) {
|
module.exports.check_android_target = function(valid_target) {
|
||||||
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.';
|
// valid_target can look like:
|
||||||
return tryCommand('android list targets', msg)
|
// 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)
|
||||||
.then(function(output) {
|
.then(function(output) {
|
||||||
if (!output.match(valid_target)) {
|
if (output.split('\n').indexOf(valid_target) == -1) {
|
||||||
throw new Error('Please install Android target "' + valid_target + '".\n' +
|
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
||||||
'Hint: Run "android" from your command-line to open the SDK manager.');
|
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)');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-9
@@ -122,7 +122,7 @@ function copyBuildRules(projectPath) {
|
|||||||
shell.cp('-f', path.join(srcDir, 'custom_rules.xml'), 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, 'build.gradle'), projectPath);
|
||||||
shell.cp('-f', path.join(srcDir, 'settings.gradle'), projectPath);
|
shell.cp('-f', path.join(srcDir, 'cordova.gradle'), projectPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyScripts(projectPath) {
|
function copyScripts(projectPath) {
|
||||||
@@ -214,7 +214,7 @@ exports.createProject = function(project_path, package_name, project_name, proje
|
|||||||
var activity_dir = path.join(project_path, 'src', package_as_path);
|
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)
|
// 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)
|
// TODO: provide option to specify activity name via CLI (proposal: https://issues.apache.org/jira/browse/CB-7231)
|
||||||
var safe_activity_name = "CordovaApp";
|
var safe_activity_name = 'MainActivity';
|
||||||
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
||||||
var target_api = check_reqs.get_target();
|
var target_api = check_reqs.get_target();
|
||||||
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
|
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
|
||||||
@@ -228,10 +228,6 @@ exports.createProject = function(project_path, package_name, project_name, proje
|
|||||||
return validatePackageName(package_name)
|
return validatePackageName(package_name)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
validateProjectName(project_name);
|
validateProjectName(project_name);
|
||||||
})
|
|
||||||
// Check that requirements are met and proper targets are installed
|
|
||||||
.then(function() {
|
|
||||||
return check_reqs.run();
|
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
// Log the given values for the project
|
// Log the given values for the project
|
||||||
console.log('Creating Cordova project for the Android platform:');
|
console.log('Creating Cordova project for the Android platform:');
|
||||||
@@ -282,7 +278,7 @@ exports.createProject = function(project_path, package_name, project_name, proje
|
|||||||
copyBuildRules(project_path);
|
copyBuildRules(project_path);
|
||||||
});
|
});
|
||||||
// Link it to local android install.
|
// Link it to local android install.
|
||||||
writeProjectProperties(project_path, target_api);
|
writeProjectProperties(project_path, target_api, use_shared_project);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log('Project successfully created.');
|
console.log('Project successfully created.');
|
||||||
});
|
});
|
||||||
@@ -307,8 +303,7 @@ function extractProjectNameFromManifest(projectPath) {
|
|||||||
// Returns a promise.
|
// Returns a promise.
|
||||||
exports.updateProject = function(projectPath, shared) {
|
exports.updateProject = function(projectPath, shared) {
|
||||||
var newVersion = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
var newVersion = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
||||||
// Check that requirements are met and proper targets are installed
|
return Q()
|
||||||
return check_reqs.run()
|
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var projectName = extractProjectNameFromManifest(projectPath);
|
var projectName = extractProjectNameFromManifest(projectPath);
|
||||||
var target_api = check_reqs.get_target();
|
var target_api = check_reqs.get_target();
|
||||||
|
|||||||
Vendored
+74
-19
@@ -20,13 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var shell = require('shelljs'),
|
var shell = require('shelljs'),
|
||||||
exec = require('./exec'),
|
|
||||||
spawn = require('./spawn'),
|
spawn = require('./spawn'),
|
||||||
Q = require('q'),
|
Q = require('q'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
ROOT = path.join(__dirname, '..', '..');
|
ROOT = path.join(__dirname, '..', '..');
|
||||||
var check_reqs = require('./check_reqs');
|
var check_reqs = require('./check_reqs');
|
||||||
|
var exec = require('./exec');
|
||||||
|
|
||||||
var LOCAL_PROPERTIES_TEMPLATE =
|
var LOCAL_PROPERTIES_TEMPLATE =
|
||||||
'# This file is automatically generated.\n' +
|
'# This file is automatically generated.\n' +
|
||||||
@@ -53,7 +53,7 @@ function sortFilesByDate(files) {
|
|||||||
}).map(function(p) { return p.p; });
|
}).map(function(p) { return p.p; });
|
||||||
}
|
}
|
||||||
|
|
||||||
function findOutputApksHelper(dir, build_type) {
|
function findOutputApksHelper(dir, build_type, arch) {
|
||||||
var ret = findApks(dir).filter(function(candidate) {
|
var ret = findApks(dir).filter(function(candidate) {
|
||||||
// Need to choose between release and debug .apk.
|
// Need to choose between release and debug .apk.
|
||||||
if (build_type === 'debug') {
|
if (build_type === 'debug') {
|
||||||
@@ -69,9 +69,15 @@ function findOutputApksHelper(dir, build_type) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
|
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
|
||||||
return ret.filter(function(p) {
|
ret = ret.filter(function(p) {
|
||||||
return !!/-x86|-arm/.exec(p) == archSpecific;
|
return !!/-x86|-arm/.exec(p) == archSpecific;
|
||||||
});
|
});
|
||||||
|
if (arch) {
|
||||||
|
ret = ret.filter(function(p) {
|
||||||
|
return p.indexOf('-' + arch) != -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasCustomRules() {
|
function hasCustomRules() {
|
||||||
@@ -163,11 +169,11 @@ var builders = {
|
|||||||
|
|
||||||
findOutputApks: function(build_type) {
|
findOutputApks: function(build_type) {
|
||||||
var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
|
var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
|
||||||
return findOutputApksHelper(binDir, build_type);
|
return findOutputApksHelper(binDir, build_type, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gradle: {
|
gradle: {
|
||||||
getArgs: function(cmd) {
|
getArgs: function(cmd, arch) {
|
||||||
var lintSteps;
|
var lintSteps;
|
||||||
if (process.env['BUILD_MULTIPLE_APKS']) {
|
if (process.env['BUILD_MULTIPLE_APKS']) {
|
||||||
lintSteps = [
|
lintSteps = [
|
||||||
@@ -187,6 +193,19 @@ var builders = {
|
|||||||
'copyDebugLint'
|
'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')];
|
var args = [cmd, '-b', path.join(ROOT, 'build.gradle')];
|
||||||
// 10 seconds -> 6 seconds
|
// 10 seconds -> 6 seconds
|
||||||
args.push('-Dorg.gradle.daemon=true');
|
args.push('-Dorg.gradle.daemon=true');
|
||||||
@@ -217,6 +236,36 @@ var builders = {
|
|||||||
shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
|
shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
|
||||||
shell.mkdir('-p', path.join(projectPath, 'gradle'));
|
shell.mkdir('-p', path.join(projectPath, 'gradle'));
|
||||||
shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), 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);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -224,10 +273,10 @@ var builders = {
|
|||||||
* Builds the project with gradle.
|
* Builds the project with gradle.
|
||||||
* Returns a promise.
|
* Returns a promise.
|
||||||
*/
|
*/
|
||||||
build: function(build_type) {
|
build: function(build_type, arch) {
|
||||||
var builder = this;
|
var builder = this;
|
||||||
var wrapper = path.join(ROOT, 'gradlew');
|
var wrapper = path.join(ROOT, 'gradlew');
|
||||||
var args = builder.getArgs('build');
|
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch);
|
||||||
return Q().then(function() {
|
return Q().then(function() {
|
||||||
return spawn(wrapper, args);
|
return spawn(wrapper, args);
|
||||||
});
|
});
|
||||||
@@ -242,9 +291,9 @@ var builders = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
findOutputApks: function(build_type) {
|
findOutputApks: function(build_type, arch) {
|
||||||
var binDir = path.join(ROOT, 'build', 'apk');
|
var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
|
||||||
return findOutputApksHelper(binDir, build_type);
|
return findOutputApksHelper(binDir, build_type, arch);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -259,19 +308,20 @@ var builders = {
|
|||||||
clean: function() {
|
clean: function() {
|
||||||
return Q();
|
return Q();
|
||||||
},
|
},
|
||||||
findOutputApks: function(build_type) {
|
findOutputApks: function(build_type, arch) {
|
||||||
return sortFilesByDate(builders.ant.findOutputApks(build_type).concat(builders.gradle.findOutputApks(build_type)));
|
return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseOpts(options) {
|
function parseOpts(options, resolvedTarget) {
|
||||||
// Backwards-compatibility: Allow a single string argument
|
// Backwards-compatibility: Allow a single string argument
|
||||||
if (typeof options == "string") options = [options];
|
if (typeof options == "string") options = [options];
|
||||||
|
|
||||||
var ret = {
|
var ret = {
|
||||||
buildType: 'debug',
|
buildType: 'debug',
|
||||||
buildMethod: process.env['ANDROID_BUILD'] || 'ant'
|
buildMethod: process.env['ANDROID_BUILD'] || 'ant',
|
||||||
|
arch: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Iterate through command line options
|
// Iterate through command line options
|
||||||
@@ -297,6 +347,12 @@ function parseOpts(options) {
|
|||||||
return Q.reject('Build option \'' + options[i] + '\' not recognized.');
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,15 +375,14 @@ module.exports.runClean = function(options) {
|
|||||||
* Builds the project with the specifed options
|
* Builds the project with the specifed options
|
||||||
* Returns a promise.
|
* Returns a promise.
|
||||||
*/
|
*/
|
||||||
module.exports.run = function(options) {
|
module.exports.run = function(options, optResolvedTarget) {
|
||||||
var opts = parseOpts(options);
|
var opts = parseOpts(options, optResolvedTarget);
|
||||||
|
|
||||||
var builder = builders[opts.buildMethod];
|
var builder = builders[opts.buildMethod];
|
||||||
return builder.prepEnv()
|
return builder.prepEnv()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return builder.build(opts.buildType);
|
return builder.build(opts.buildType, opts.arch);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
var apkPaths = builder.findOutputApks(opts.buildType);
|
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
|
||||||
console.log('Built the following apk(s):');
|
console.log('Built the following apk(s):');
|
||||||
console.log(' ' + apkPaths.join('\n '));
|
console.log(' ' + apkPaths.join('\n '));
|
||||||
return {
|
return {
|
||||||
|
|||||||
Vendored
+46
-34
@@ -43,48 +43,60 @@ 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
|
* Installs a previously built application on the device
|
||||||
* and launches it.
|
* and launches it.
|
||||||
* Returns a promise.
|
* Returns a promise.
|
||||||
*/
|
*/
|
||||||
module.exports.install = function(target, buildResults) {
|
module.exports.install = function(target, buildResults) {
|
||||||
var launchName;
|
return Q().then(function() {
|
||||||
return this.list()
|
if (target && typeof target == 'object') {
|
||||||
.then(function(device_list) {
|
return target;
|
||||||
if (!device_list || !device_list.length)
|
}
|
||||||
return Q.reject('ERROR: Failed to deploy to device, no devices found.');
|
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);
|
||||||
|
|
||||||
// default device
|
//unlock screen
|
||||||
target = target || device_list[0];
|
var cmd = 'adb -s ' + resolvedTarget.target + ' shell input keyevent 82';
|
||||||
|
|
||||||
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);
|
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-43
@@ -28,6 +28,7 @@ var shell = require('shelljs'),
|
|||||||
ROOT = path.join(__dirname, '..', '..'),
|
ROOT = path.join(__dirname, '..', '..'),
|
||||||
child_process = require('child_process'),
|
child_process = require('child_process'),
|
||||||
new_emulator = 'cordova_emulator';
|
new_emulator = 'cordova_emulator';
|
||||||
|
var check_reqs = require('./check_reqs');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Promise for a list of emulator images in the form of objects
|
* Returns a Promise for a list of emulator images in the form of objects
|
||||||
@@ -84,7 +85,7 @@ module.exports.list_images = function() {
|
|||||||
* Returns a promise.
|
* Returns a promise.
|
||||||
*/
|
*/
|
||||||
module.exports.best_image = function() {
|
module.exports.best_image = function() {
|
||||||
var project_target = this.get_target().replace('android-', '');
|
var project_target = check_reqs.get_target().replace('android-', '');
|
||||||
return this.list_images()
|
return this.list_images()
|
||||||
.then(function(images) {
|
.then(function(images) {
|
||||||
var closest = 9999;
|
var closest = 9999;
|
||||||
@@ -120,11 +121,6 @@ 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.
|
// Returns a promise.
|
||||||
module.exports.list_targets = function() {
|
module.exports.list_targets = function() {
|
||||||
return exec('android list targets')
|
return exec('android list targets')
|
||||||
@@ -156,7 +152,7 @@ module.exports.start = function(emulator_ID) {
|
|||||||
.then(function(list) {
|
.then(function(list) {
|
||||||
started_emulators = list;
|
started_emulators = list;
|
||||||
num_started = started_emulators.length;
|
num_started = started_emulators.length;
|
||||||
if (typeof emulator_ID === 'undefined') {
|
if (!emulator_ID) {
|
||||||
return self.list_images()
|
return self.list_images()
|
||||||
.then(function(emulator_list) {
|
.then(function(emulator_list) {
|
||||||
if (emulator_list.length > 0) {
|
if (emulator_list.length > 0) {
|
||||||
@@ -167,11 +163,11 @@ module.exports.start = function(emulator_ID) {
|
|||||||
return emulator_ID;
|
return emulator_ID;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return Q.reject('ERROR : No emulator images (avds) found, if you would like to create an\n' +
|
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
|
||||||
' avd follow the instructions provided here:\n' +
|
return Q.reject('ERROR : No emulator images (avds) found.\n' +
|
||||||
' http://developer.android.com/tools/devices/index.html\n' +
|
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
|
||||||
' Or run \'android create avd --name <name> --target <targetID>\'\n' +
|
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
||||||
' in on the command line.');
|
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -277,14 +273,7 @@ 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()
|
return this.list_started()
|
||||||
.then(function(emulator_list) {
|
.then(function(emulator_list) {
|
||||||
if (emulator_list.length < 1) {
|
if (emulator_list.length < 1) {
|
||||||
@@ -299,30 +288,48 @@ module.exports.install = function(target, buildResults) {
|
|||||||
|
|
||||||
return build.detectArchitecture(target)
|
return build.detectArchitecture(target)
|
||||||
.then(function(arch) {
|
.then(function(arch) {
|
||||||
var apk_path = build.findBestApkForArchitecture(buildResults, arch);
|
return {target:target, arch:arch, isEmulator:true};
|
||||||
console.log('Installing app on emulator...');
|
|
||||||
console.log('Using apk: ' + apk_path);
|
|
||||||
return exec('adb -s ' + target + ' install -r "' + apk_path + '"');
|
|
||||||
});
|
});
|
||||||
}).then(function(output) {
|
});
|
||||||
if (output.match(/Failure/)) {
|
};
|
||||||
return Q.reject('Failed to install apk to emulator: ' + output);
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
return Q();
|
return module.exports.resolveTarget(target);
|
||||||
}, function(err) {
|
}).then(function(resolvedTarget) {
|
||||||
return Q.reject('Failed to install apk to emulator: ' + err);
|
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||||
}).then(function() {
|
console.log('Installing app on emulator...');
|
||||||
//unlock screen
|
console.log('Using apk: ' + apk_path);
|
||||||
return exec('adb -s ' + target + ' shell input keyevent 82');
|
return exec('adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"')
|
||||||
}).then(function() {
|
.then(function(output) {
|
||||||
// launch the application
|
if (output.match(/Failure/)) {
|
||||||
console.log('Launching application...');
|
return Q.reject('Failed to install apk to emulator: ' + output);
|
||||||
var launchName = appinfo.getActivityName();
|
}
|
||||||
cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
|
return Q();
|
||||||
return exec(cmd);
|
}, function(err) {
|
||||||
}).then(function(output) {
|
return Q.reject('Failed to install apk to emulator: ' + err);
|
||||||
console.log('LAUNCH SUCCESS');
|
}).then(function() {
|
||||||
}, function(err) {
|
//unlock screen
|
||||||
return Q.reject('Failed to launch app on emulator: ' + err);
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/* 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'
|
||||||
|
}
|
||||||
Vendored
+51
-58
@@ -55,73 +55,66 @@ var path = require('path'),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return build.run(buildFlags).then(function(buildResults) {
|
return Q()
|
||||||
if (install_target == '--device') {
|
.then(function() {
|
||||||
return device.install(null, buildResults);
|
if (!install_target) {
|
||||||
} 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.
|
// no target given, deploy to device if available, otherwise use the emulator.
|
||||||
return device.list()
|
return device.list()
|
||||||
.then(function(device_list) {
|
.then(function(device_list) {
|
||||||
if (device_list.length > 0) {
|
if (device_list.length > 0) {
|
||||||
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
|
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
|
||||||
return device.install(device_list[0], buildResults);
|
install_target = device_list[0];
|
||||||
} else {
|
} else {
|
||||||
return emulator.list_started()
|
console.log('WARNING : No target specified, deploying to emulator');
|
||||||
.then(function(emulator_list) {
|
install_target = '--emulator';
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}).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 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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Coho updates this line:
|
// Coho updates this line:
|
||||||
var VERSION = "3.6.4";
|
var VERSION = "3.7.0-dev";
|
||||||
|
|
||||||
console.log(VERSION);
|
console.log(VERSION);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
||||||
android:hardwareAccelerated="true">
|
android:hardwareAccelerated="true" android:supportsRtl="true">
|
||||||
<activity android:name="__ACTIVITY__"
|
<activity android:name="__ACTIVITY__"
|
||||||
android:label="@string/activity_name"
|
android:label="@string/activity_name"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
import java.util.regex.Pattern
|
/*
|
||||||
|
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'
|
apply plugin: 'android'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
@@ -8,19 +32,16 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:0.10.+'
|
classpath 'com.android.tools.build:gradle:0.12.0+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task wrapper(type: Wrapper) {
|
||||||
|
gradleVersion = '1.12'
|
||||||
|
}
|
||||||
|
|
||||||
ext.multiarch=false
|
ext.multiarch=false
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
|
||||||
for (subproject in getProjectList()) {
|
|
||||||
compile project(subproject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
@@ -35,11 +56,11 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode Integer.parseInt("" + getVersionCodeFromManifest() + "0")
|
versionCode Integer.parseInt(System.env.ANDROID_VERSION_CODE ?: ("" + getVersionCodeFromManifest() + "0"))
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdkVersion 19
|
compileSdkVersion cordova.cordovaSdkVersion
|
||||||
buildToolsVersion "19.0.0"
|
buildToolsVersion cordova.cordovaBuildToolsVersion
|
||||||
|
|
||||||
if (multiarch || System.env.BUILD_MULTIPLE_APKS) {
|
if (multiarch || System.env.BUILD_MULTIPLE_APKS) {
|
||||||
productFlavors {
|
productFlavors {
|
||||||
@@ -68,10 +89,78 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_7
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task wrapper(type: Wrapper) {
|
dependencies {
|
||||||
gradleVersion = '1.12'
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVersionCodeFromManifest() {
|
def getVersionCodeFromManifest() {
|
||||||
@@ -82,13 +171,45 @@ def getVersionCodeFromManifest() {
|
|||||||
return Integer.parseInt(matcher.group(1))
|
return Integer.parseInt(matcher.group(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
def getProjectList() {
|
def ensureValueExists(filePath, props, key) {
|
||||||
def manifestFile = file("project.properties")
|
if (props.get(key) == null) {
|
||||||
def pattern = Pattern.compile("android.library.reference.(\\d+)\\s*=\\s*(.*)")
|
throw new GradleException(filePath + ': Missing key required "' + key + '"')
|
||||||
def matcher = pattern.matcher(manifestFile.getText())
|
|
||||||
def projects = []
|
|
||||||
while (matcher.find()) {
|
|
||||||
projects.add(":" + matcher.group(2).replace("/",":"))
|
|
||||||
}
|
}
|
||||||
return projects
|
return props.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
def addSigningProps(propsFilePath, signingConfig) {
|
||||||
|
def propsFile = file(propsFilePath)
|
||||||
|
def props = new Properties()
|
||||||
|
propsFile.withReader { reader ->
|
||||||
|
props.load(reader)
|
||||||
|
}
|
||||||
|
def storeFile = new File(ensureValueExists(propsFilePath, props, 'storeFile'))
|
||||||
|
if (!storeFile.isAbsolute()) {
|
||||||
|
storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
|
||||||
|
}
|
||||||
|
if (!storeFile.exists()) {
|
||||||
|
throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
|
||||||
|
}
|
||||||
|
signingConfig.keyAlias = ensureValueExists(propsFilePath, props, 'keyAlias')
|
||||||
|
signingConfig.keyPassword = props.get('keyPassword')
|
||||||
|
signingConfig.storeFile = storeFile
|
||||||
|
signingConfig.storePassword = props.get('storePassword')
|
||||||
|
def storeType = props.get('storeType')
|
||||||
|
if (!storeType) {
|
||||||
|
def filename = storeFile.getName().toLowerCase();
|
||||||
|
if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
|
||||||
|
storeType = 'pkcs12'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (storeType) {
|
||||||
|
signingConfig.storeType = storeType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PLUGIN GRADLE EXTENSIONS START
|
||||||
|
// PLUGIN GRADLE EXTENSIONS END
|
||||||
|
|
||||||
|
if (file('build-extras.gradle').exists()) {
|
||||||
|
apply from: 'build-extras.gradle'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
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")
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ local.properties
|
|||||||
/gradlew.bat
|
/gradlew.bat
|
||||||
/gradle
|
/gradle
|
||||||
# Ant builds
|
# Ant builds
|
||||||
ant-built
|
ant-build
|
||||||
ant-gen
|
ant-gen
|
||||||
# Eclipse builds
|
# Eclipse builds
|
||||||
gen
|
gen
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
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 ':'
|
|
||||||
Vendored
+63
-49
@@ -1,5 +1,5 @@
|
|||||||
// Platform: android
|
// Platform: android
|
||||||
// 8ca0f3b2b87e0759c5236b91c80f18438544409c
|
// 1fc2526faa6197e1637ecb48ebe0f876f008ba0f
|
||||||
/*
|
/*
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
or more contributor license agreements. See the NOTICE file
|
or more contributor license agreements. See the NOTICE file
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
;(function() {
|
;(function() {
|
||||||
var PLATFORM_VERSION_BUILD_LABEL = '3.6.4';
|
var PLATFORM_VERSION_BUILD_LABEL = '3.7.0-dev';
|
||||||
// file: src/scripts/require.js
|
// file: src/scripts/require.js
|
||||||
|
|
||||||
/*jshint -W079 */
|
/*jshint -W079 */
|
||||||
@@ -263,11 +263,7 @@ var cordova = {
|
|||||||
* Called by native code when returning successful result from an action.
|
* Called by native code when returning successful result from an action.
|
||||||
*/
|
*/
|
||||||
callbackSuccess: function(callbackId, args) {
|
callbackSuccess: function(callbackId, args) {
|
||||||
try {
|
cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
|
||||||
cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
|
|
||||||
} catch (e) {
|
|
||||||
console.log("Error in success callback: " + callbackId + " = "+e);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,30 +272,34 @@ var cordova = {
|
|||||||
callbackError: function(callbackId, args) {
|
callbackError: function(callbackId, args) {
|
||||||
// TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
|
// TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
|
||||||
// Derive success from status.
|
// Derive success from status.
|
||||||
try {
|
cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
|
||||||
cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
|
|
||||||
} catch (e) {
|
|
||||||
console.log("Error in error callback: " + callbackId + " = "+e);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by native code when returning the result from an action.
|
* Called by native code when returning the result from an action.
|
||||||
*/
|
*/
|
||||||
callbackFromNative: function(callbackId, success, status, args, keepCallback) {
|
callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
|
||||||
var callback = cordova.callbacks[callbackId];
|
try {
|
||||||
if (callback) {
|
var callback = cordova.callbacks[callbackId];
|
||||||
if (success && status == cordova.callbackStatus.OK) {
|
if (callback) {
|
||||||
callback.success && callback.success.apply(null, args);
|
if (isSuccess && status == cordova.callbackStatus.OK) {
|
||||||
} else if (!success) {
|
callback.success && callback.success.apply(null, args);
|
||||||
callback.fail && callback.fail.apply(null, args);
|
} else {
|
||||||
}
|
callback.fail && callback.fail.apply(null, args);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear callback if not expecting any more results
|
// Clear callback if not expecting any more results
|
||||||
if (!keepCallback) {
|
if (!keepCallback) {
|
||||||
delete cordova.callbacks[callbackId];
|
delete cordova.callbacks[callbackId];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (err) {
|
||||||
|
var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
|
||||||
|
console && console.log && console.log(msg);
|
||||||
|
cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
addConstructor: function(func) {
|
addConstructor: function(func) {
|
||||||
channel.onCordovaReady.subscribe(function() {
|
channel.onCordovaReady.subscribe(function() {
|
||||||
@@ -1013,6 +1013,42 @@ androidExec.setNativeToJsBridgeMode = function(mode) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function buildPayload(payload, message) {
|
||||||
|
var payloadKind = message.charAt(0);
|
||||||
|
if (payloadKind == 's') {
|
||||||
|
payload.push(message.slice(1));
|
||||||
|
} else if (payloadKind == 't') {
|
||||||
|
payload.push(true);
|
||||||
|
} else if (payloadKind == 'f') {
|
||||||
|
payload.push(false);
|
||||||
|
} else if (payloadKind == 'N') {
|
||||||
|
payload.push(null);
|
||||||
|
} else if (payloadKind == 'n') {
|
||||||
|
payload.push(+message.slice(1));
|
||||||
|
} else if (payloadKind == 'A') {
|
||||||
|
var data = message.slice(1);
|
||||||
|
var bytes = window.atob(data);
|
||||||
|
var arraybuffer = new Uint8Array(bytes.length);
|
||||||
|
for (var i = 0; i < bytes.length; i++) {
|
||||||
|
arraybuffer[i] = bytes.charCodeAt(i);
|
||||||
|
}
|
||||||
|
payload.push(arraybuffer.buffer);
|
||||||
|
} else if (payloadKind == 'S') {
|
||||||
|
payload.push(window.atob(message.slice(1)));
|
||||||
|
} else if (payloadKind == 'M') {
|
||||||
|
var multipartMessages = message.slice(1);
|
||||||
|
while (multipartMessages !== "") {
|
||||||
|
var spaceIdx = multipartMessages.indexOf(' ');
|
||||||
|
var msgLen = +multipartMessages.slice(0, spaceIdx);
|
||||||
|
var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
|
||||||
|
multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
|
||||||
|
buildPayload(payload, multipartMessage);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
payload.push(JSON.parse(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Processes a single message, as encoded by NativeToJsMessageQueue.java.
|
// Processes a single message, as encoded by NativeToJsMessageQueue.java.
|
||||||
function processMessage(message) {
|
function processMessage(message) {
|
||||||
try {
|
try {
|
||||||
@@ -1026,32 +1062,10 @@ function processMessage(message) {
|
|||||||
var status = +message.slice(2, spaceIdx);
|
var status = +message.slice(2, spaceIdx);
|
||||||
var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
|
var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
|
||||||
var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
|
var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
|
||||||
var payloadKind = message.charAt(nextSpaceIdx + 1);
|
var payloadMessage = message.slice(nextSpaceIdx + 1);
|
||||||
var payload;
|
var payload = [];
|
||||||
if (payloadKind == 's') {
|
buildPayload(payload, payloadMessage);
|
||||||
payload = message.slice(nextSpaceIdx + 2);
|
cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
|
||||||
} else if (payloadKind == 't') {
|
|
||||||
payload = true;
|
|
||||||
} else if (payloadKind == 'f') {
|
|
||||||
payload = false;
|
|
||||||
} else if (payloadKind == 'N') {
|
|
||||||
payload = null;
|
|
||||||
} else if (payloadKind == 'n') {
|
|
||||||
payload = +message.slice(nextSpaceIdx + 2);
|
|
||||||
} else if (payloadKind == 'A') {
|
|
||||||
var data = message.slice(nextSpaceIdx + 2);
|
|
||||||
var bytes = window.atob(data);
|
|
||||||
var arraybuffer = new Uint8Array(bytes.length);
|
|
||||||
for (var i = 0; i < bytes.length; i++) {
|
|
||||||
arraybuffer[i] = bytes.charCodeAt(i);
|
|
||||||
}
|
|
||||||
payload = arraybuffer.buffer;
|
|
||||||
} else if (payloadKind == 'S') {
|
|
||||||
payload = window.atob(message.slice(nextSpaceIdx + 2));
|
|
||||||
} else {
|
|
||||||
payload = JSON.parse(message.slice(nextSpaceIdx + 1));
|
|
||||||
}
|
|
||||||
cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
|
|
||||||
} else {
|
} else {
|
||||||
console.log("processMessage failed: invalid message: " + JSON.stringify(message));
|
console.log("processMessage failed: invalid message: " + JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-18
@@ -1,20 +1,19 @@
|
|||||||
/*
|
/* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
or more contributor license agreements. See the NOTICE file
|
||||||
or more contributor license agreements. See the NOTICE file
|
distributed with this work for additional information
|
||||||
distributed with this work for additional information
|
regarding copyright ownership. The ASF licenses this file
|
||||||
regarding copyright ownership. The ASF licenses this file
|
to you under the Apache License, Version 2.0 (the
|
||||||
to you under the Apache License, Version 2.0 (the
|
"License"); you may not use this file except in compliance
|
||||||
"License"); you may not use this file except in compliance
|
with the License. You may obtain a copy of the License at
|
||||||
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,
|
Unless required by applicable law or agreed to in writing,
|
||||||
software distributed under the License is distributed on an
|
software distributed under the License is distributed on an
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
KIND, either express or implied. See the License for the
|
KIND, either express or implied. See the License for the
|
||||||
specific language governing permissions and limitations
|
specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -25,15 +24,25 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:0.10.+'
|
// 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.+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'android-library'
|
apply plugin: 'android-library'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 19
|
compileSdkVersion cordova.cordovaSdkVersion
|
||||||
buildToolsVersion "19.0.0"
|
buildToolsVersion cordova.cordovaBuildToolsVersion
|
||||||
|
publishNonDefault true
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cordova;
|
package org.apache.cordova;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
import org.apache.cordova.PluginManager;
|
import org.apache.cordova.PluginManager;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@@ -35,12 +37,14 @@ public class CordovaBridge {
|
|||||||
private NativeToJsMessageQueue jsMessageQueue;
|
private NativeToJsMessageQueue jsMessageQueue;
|
||||||
private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
|
private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
|
||||||
private String loadedUrl;
|
private String loadedUrl;
|
||||||
|
private String appContentUrlPrefix;
|
||||||
|
|
||||||
public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
|
public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue, String packageName) {
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
this.jsMessageQueue = jsMessageQueue;
|
this.jsMessageQueue = jsMessageQueue;
|
||||||
|
this.appContentUrlPrefix = "content://" + packageName + ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
|
public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
|
||||||
if (!verifySecret("exec()", bridgeSecret)) {
|
if (!verifySecret("exec()", bridgeSecret)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -107,7 +111,8 @@ public class CordovaBridge {
|
|||||||
|
|
||||||
/** Called by cordova.js to initialize the bridge. */
|
/** Called by cordova.js to initialize the bridge. */
|
||||||
int generateBridgeSecret() {
|
int generateBridgeSecret() {
|
||||||
expectedBridgeSecret = (int)(Math.random() * Integer.MAX_VALUE);
|
SecureRandom randGen = new SecureRandom();
|
||||||
|
expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
|
||||||
return expectedBridgeSecret;
|
return expectedBridgeSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +167,9 @@ public class CordovaBridge {
|
|||||||
// Protect against random iframes being able to talk through the bridge.
|
// Protect against random iframes being able to talk through the bridge.
|
||||||
// Trust only file URLs and the start URL's domain.
|
// Trust only file URLs and the start URL's domain.
|
||||||
// The extra origin.startsWith("http") is to protect against iframes with data: having "" as origin.
|
// The extra origin.startsWith("http") is to protect against iframes with data: having "" as origin.
|
||||||
if (origin.startsWith("file:") || (origin.startsWith("http") && loadedUrl.startsWith(origin))) {
|
if (origin.startsWith("file:") ||
|
||||||
|
origin.startsWith(this.appContentUrlPrefix) ||
|
||||||
|
(origin.startsWith("http") && loadedUrl.startsWith(origin))) {
|
||||||
// Enable the bridge
|
// Enable the bridge
|
||||||
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
|
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
|
||||||
jsMessageQueue.setBridgeMode(bridgeMode);
|
jsMessageQueue.setBridgeMode(bridgeMode);
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ public class CordovaChromeClient extends WebChromeClient {
|
|||||||
// the video progress view
|
// the video progress view
|
||||||
private View mVideoProgressView;
|
private View mVideoProgressView;
|
||||||
|
|
||||||
|
//Keep track of last AlertDialog showed
|
||||||
|
private AlertDialog lastHandledDialog;
|
||||||
|
|
||||||
// File Chooser
|
// File Chooser
|
||||||
public ValueCallback<Uri> mUploadMessage;
|
public ValueCallback<Uri> mUploadMessage;
|
||||||
|
|
||||||
@@ -123,7 +126,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dlg.show();
|
lastHandledDialog = dlg.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dlg.show();
|
lastHandledDialog = dlg.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +219,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
|||||||
res.cancel();
|
res.cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dlg.show();
|
lastHandledDialog = dlg.show();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -328,4 +331,11 @@ public class CordovaChromeClient extends WebChromeClient {
|
|||||||
public ValueCallback<Uri> getValueCallback() {
|
public ValueCallback<Uri> getValueCallback() {
|
||||||
return this.mUploadMessage;
|
return this.mUploadMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void destroyLastDialog(){
|
||||||
|
if(lastHandledDialog != null){
|
||||||
|
lastHandledDialog.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ import android.widget.FrameLayout;
|
|||||||
public class CordovaWebView extends WebView {
|
public class CordovaWebView extends WebView {
|
||||||
|
|
||||||
public static final String TAG = "CordovaWebView";
|
public static final String TAG = "CordovaWebView";
|
||||||
public static final String CORDOVA_VERSION = "3.6.4";
|
public static final String CORDOVA_VERSION = "3.7.0-dev";
|
||||||
|
|
||||||
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
|
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ public class CordovaWebView extends WebView {
|
|||||||
super.setWebViewClient(webViewClient);
|
super.setWebViewClient(webViewClient);
|
||||||
|
|
||||||
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
|
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
|
||||||
bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova));
|
bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova), this.cordova.getActivity().getPackageName());
|
||||||
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
|
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
|
||||||
|
|
||||||
pluginManager.addService("App", "org.apache.cordova.App");
|
pluginManager.addService("App", "org.apache.cordova.App");
|
||||||
@@ -788,6 +788,9 @@ public class CordovaWebView extends WebView {
|
|||||||
|
|
||||||
// Load blank page so that JavaScript onunload is called
|
// Load blank page so that JavaScript onunload is called
|
||||||
this.loadUrl("about:blank");
|
this.loadUrl("about:blank");
|
||||||
|
|
||||||
|
//Remove last AlertDialog
|
||||||
|
this.chromeClient.destroyLastDialog();
|
||||||
|
|
||||||
// Forward to plugins
|
// Forward to plugins
|
||||||
if (this.pluginManager != null) {
|
if (this.pluginManager != null) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public class NativeToJsMessageQueue {
|
|||||||
|
|
||||||
// Set this to true to force plugin results to be encoding as
|
// Set this to true to force plugin results to be encoding as
|
||||||
// JS instead of the custom format (useful for benchmarking).
|
// JS instead of the custom format (useful for benchmarking).
|
||||||
|
// Doesn't work for multipart messages.
|
||||||
private static final boolean FORCE_ENCODE_USING_EVAL = false;
|
private static final boolean FORCE_ENCODE_USING_EVAL = false;
|
||||||
|
|
||||||
// Disable sending back native->JS messages during an exec() when the active
|
// Disable sending back native->JS messages during an exec() when the active
|
||||||
@@ -419,53 +420,43 @@ public class NativeToJsMessageQueue {
|
|||||||
this.pluginResult = pluginResult;
|
this.pluginResult = pluginResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int calculateEncodedLengthHelper(PluginResult pluginResult) {
|
||||||
|
switch (pluginResult.getMessageType()) {
|
||||||
|
case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
|
||||||
|
case PluginResult.MESSAGE_TYPE_NULL: // N
|
||||||
|
return 1;
|
||||||
|
case PluginResult.MESSAGE_TYPE_NUMBER: // n
|
||||||
|
return 1 + pluginResult.getMessage().length();
|
||||||
|
case PluginResult.MESSAGE_TYPE_STRING: // s
|
||||||
|
return 1 + pluginResult.getStrMessage().length();
|
||||||
|
case PluginResult.MESSAGE_TYPE_BINARYSTRING:
|
||||||
|
return 1 + pluginResult.getMessage().length();
|
||||||
|
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
|
||||||
|
return 1 + pluginResult.getMessage().length();
|
||||||
|
case PluginResult.MESSAGE_TYPE_MULTIPART:
|
||||||
|
int ret = 1;
|
||||||
|
for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
|
||||||
|
int length = calculateEncodedLengthHelper(pluginResult.getMultipartMessage(i));
|
||||||
|
int argLength = String.valueOf(length).length();
|
||||||
|
ret += argLength + 1 + length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
case PluginResult.MESSAGE_TYPE_JSON:
|
||||||
|
default:
|
||||||
|
return pluginResult.getMessage().length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int calculateEncodedLength() {
|
int calculateEncodedLength() {
|
||||||
if (pluginResult == null) {
|
if (pluginResult == null) {
|
||||||
return jsPayloadOrCallbackId.length() + 1;
|
return jsPayloadOrCallbackId.length() + 1;
|
||||||
}
|
}
|
||||||
int statusLen = String.valueOf(pluginResult.getStatus()).length();
|
int statusLen = String.valueOf(pluginResult.getStatus()).length();
|
||||||
int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
|
int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
|
||||||
switch (pluginResult.getMessageType()) {
|
return ret + calculateEncodedLengthHelper(pluginResult);
|
||||||
case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
|
|
||||||
case PluginResult.MESSAGE_TYPE_NULL: // N
|
|
||||||
ret += 1;
|
|
||||||
break;
|
|
||||||
case PluginResult.MESSAGE_TYPE_NUMBER: // n
|
|
||||||
ret += 1 + pluginResult.getMessage().length();
|
|
||||||
break;
|
|
||||||
case PluginResult.MESSAGE_TYPE_STRING: // s
|
|
||||||
ret += 1 + pluginResult.getStrMessage().length();
|
|
||||||
break;
|
|
||||||
case PluginResult.MESSAGE_TYPE_BINARYSTRING:
|
|
||||||
ret += 1 + pluginResult.getMessage().length();
|
|
||||||
break;
|
|
||||||
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
|
|
||||||
ret += 1 + pluginResult.getMessage().length();
|
|
||||||
break;
|
|
||||||
case PluginResult.MESSAGE_TYPE_JSON:
|
|
||||||
default:
|
|
||||||
ret += pluginResult.getMessage().length();
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void encodeAsMessage(StringBuilder sb) {
|
|
||||||
if (pluginResult == null) {
|
|
||||||
sb.append('J')
|
|
||||||
.append(jsPayloadOrCallbackId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int status = pluginResult.getStatus();
|
|
||||||
boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
|
|
||||||
boolean resultOk = status == PluginResult.Status.OK.ordinal();
|
|
||||||
boolean keepCallback = pluginResult.getKeepCallback();
|
|
||||||
|
|
||||||
sb.append((noResult || resultOk) ? 'S' : 'F')
|
static void encodeAsMessageHelper(StringBuilder sb, PluginResult pluginResult) {
|
||||||
.append(keepCallback ? '1' : '0')
|
|
||||||
.append(status)
|
|
||||||
.append(' ')
|
|
||||||
.append(jsPayloadOrCallbackId)
|
|
||||||
.append(' ');
|
|
||||||
switch (pluginResult.getMessageType()) {
|
switch (pluginResult.getMessageType()) {
|
||||||
case PluginResult.MESSAGE_TYPE_BOOLEAN:
|
case PluginResult.MESSAGE_TYPE_BOOLEAN:
|
||||||
sb.append(pluginResult.getMessage().charAt(0)); // t or f.
|
sb.append(pluginResult.getMessage().charAt(0)); // t or f.
|
||||||
@@ -489,12 +480,42 @@ public class NativeToJsMessageQueue {
|
|||||||
sb.append('A');
|
sb.append('A');
|
||||||
sb.append(pluginResult.getMessage());
|
sb.append(pluginResult.getMessage());
|
||||||
break;
|
break;
|
||||||
|
case PluginResult.MESSAGE_TYPE_MULTIPART:
|
||||||
|
sb.append('M');
|
||||||
|
for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
|
||||||
|
PluginResult multipartMessage = pluginResult.getMultipartMessage(i);
|
||||||
|
sb.append(String.valueOf(calculateEncodedLengthHelper(multipartMessage)));
|
||||||
|
sb.append(' ');
|
||||||
|
encodeAsMessageHelper(sb, multipartMessage);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PluginResult.MESSAGE_TYPE_JSON:
|
case PluginResult.MESSAGE_TYPE_JSON:
|
||||||
default:
|
default:
|
||||||
sb.append(pluginResult.getMessage()); // [ or {
|
sb.append(pluginResult.getMessage()); // [ or {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void encodeAsMessage(StringBuilder sb) {
|
||||||
|
if (pluginResult == null) {
|
||||||
|
sb.append('J')
|
||||||
|
.append(jsPayloadOrCallbackId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int status = pluginResult.getStatus();
|
||||||
|
boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
|
||||||
|
boolean resultOk = status == PluginResult.Status.OK.ordinal();
|
||||||
|
boolean keepCallback = pluginResult.getKeepCallback();
|
||||||
|
|
||||||
|
sb.append((noResult || resultOk) ? 'S' : 'F')
|
||||||
|
.append(keepCallback ? '1' : '0')
|
||||||
|
.append(status)
|
||||||
|
.append(' ')
|
||||||
|
.append(jsPayloadOrCallbackId)
|
||||||
|
.append(' ');
|
||||||
|
|
||||||
|
encodeAsMessageHelper(sb, pluginResult);
|
||||||
|
}
|
||||||
|
|
||||||
void encodeAsJsMessage(StringBuilder sb) {
|
void encodeAsJsMessage(StringBuilder sb) {
|
||||||
if (pluginResult == null) {
|
if (pluginResult == null) {
|
||||||
sb.append(jsPayloadOrCallbackId);
|
sb.append(jsPayloadOrCallbackId);
|
||||||
|
|||||||
Executable → Regular
+19
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cordova;
|
package org.apache.cordova;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ public class PluginResult {
|
|||||||
private boolean keepCallback = false;
|
private boolean keepCallback = false;
|
||||||
private String strMessage;
|
private String strMessage;
|
||||||
private String encodedMessage;
|
private String encodedMessage;
|
||||||
|
private List<PluginResult> multipartMessages;
|
||||||
|
|
||||||
public PluginResult(Status status) {
|
public PluginResult(Status status) {
|
||||||
this(status, PluginResult.StatusMessages[status.ordinal()]);
|
this(status, PluginResult.StatusMessages[status.ordinal()]);
|
||||||
@@ -80,6 +83,13 @@ public class PluginResult {
|
|||||||
this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
|
this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The keepCallback and status of multipartMessages are ignored.
|
||||||
|
public PluginResult(Status status, List<PluginResult> multipartMessages) {
|
||||||
|
this.status = status.ordinal();
|
||||||
|
this.messageType = MESSAGE_TYPE_MULTIPART;
|
||||||
|
this.multipartMessages = multipartMessages;
|
||||||
|
}
|
||||||
|
|
||||||
public void setKeepCallback(boolean b) {
|
public void setKeepCallback(boolean b) {
|
||||||
this.keepCallback = b;
|
this.keepCallback = b;
|
||||||
}
|
}
|
||||||
@@ -99,6 +109,14 @@ public class PluginResult {
|
|||||||
return encodedMessage;
|
return encodedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMultipartMessagesSize() {
|
||||||
|
return multipartMessages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult getMultipartMessage(int index) {
|
||||||
|
return multipartMessages.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If messageType == MESSAGE_TYPE_STRING, then returns the message string.
|
* If messageType == MESSAGE_TYPE_STRING, then returns the message string.
|
||||||
* Otherwise, returns null.
|
* Otherwise, returns null.
|
||||||
@@ -150,6 +168,7 @@ public class PluginResult {
|
|||||||
// Use BINARYSTRING when your string may contain null characters.
|
// Use BINARYSTRING when your string may contain null characters.
|
||||||
// This is required to work around a bug in the platform :(.
|
// This is required to work around a bug in the platform :(.
|
||||||
public static final int MESSAGE_TYPE_BINARYSTRING = 7;
|
public static final int MESSAGE_TYPE_BINARYSTRING = 7;
|
||||||
|
public static final int MESSAGE_TYPE_MULTIPART = 8;
|
||||||
|
|
||||||
public static String[] StatusMessages = new String[] {
|
public static String[] StatusMessages = new String[] {
|
||||||
"No result",
|
"No result",
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cordova-android",
|
"name": "cordova-android",
|
||||||
"version": "3.6.4",
|
"version": "3.7.0-dev",
|
||||||
"description": "cordova-android release",
|
"description": "cordova-android release",
|
||||||
"main": "bin/create",
|
"main": "bin/create",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
"apache"
|
"apache"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jasmine-node --color spec"
|
"test": "jasmine-node --color spec",
|
||||||
|
"test-build": "rm -rf \"test create\"; ./bin/create \"test create\" com.test.app 応用 && \"./test create/cordova/build\" && rm -rf \"test create\""
|
||||||
},
|
},
|
||||||
"author": "Apache Software Foundation",
|
"author": "Apache Software Foundation",
|
||||||
"license": "Apache version 2.0",
|
"license": "Apache version 2.0",
|
||||||
|
|||||||
+1
-1
@@ -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:
|
To run manually from command line:
|
||||||
|
|
||||||
0. Build by entering `ant debug install`
|
0. Build by entering `ant debug install`
|
||||||
0. Run tests by clicking on "CordovaTest" icon on device
|
0. Run tests by clicking on "CordovaNativeTests" app icon on the device
|
||||||
|
|
||||||
To run from Eclipse:
|
To run from Eclipse:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user