forked from github/cordova-android
Compare commits
79 Commits
CheckIn_no
...
Gitignore_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
0cde8819cf | ||
|
|
07632b0eeb | ||
|
|
4a7f825cfe | ||
|
|
4bc2051f44 | ||
|
|
34dde53506 | ||
|
|
7a09182446 | ||
|
|
eb8cf56e8e | ||
|
|
12a27643db | ||
|
|
c6ccde0558 | ||
|
|
16e3ebd87b | ||
|
|
94c096dd5b | ||
|
|
2e3e4ec3b2 | ||
|
|
6e222c3938 | ||
|
|
3b3bd9b6c9 | ||
|
|
4e3331ba66 | ||
|
|
b6c5a5fc9a | ||
|
|
94943a9a84 | ||
|
|
71e72f215d | ||
|
|
58cdfd86d0 | ||
|
|
dfa66b9dd4 | ||
|
|
d56ea25816 | ||
|
|
c91b272648 | ||
|
|
ca8bb75b40 | ||
|
|
36eab713a1 | ||
|
|
7133576fe9 | ||
|
|
effffcba1d | ||
|
|
404ce8bc3e | ||
|
|
a91bd095b0 | ||
|
|
8b55a16986 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -37,3 +37,6 @@ Desktop.ini
|
||||
# IntelliJ IDEA files
|
||||
*.iml
|
||||
.idea
|
||||
npm-debug.log
|
||||
/node_modules
|
||||
/framework/build
|
||||
|
||||
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
language: android
|
||||
install: npm install
|
||||
script:
|
||||
- npm test
|
||||
- npm run test-build
|
||||
140
RELEASENOTES.md
140
RELEASENOTES.md
@@ -20,6 +20,146 @@
|
||||
-->
|
||||
## Release Notes for Cordova (Android) ##
|
||||
|
||||
### 3.6.4 (Sept 30, 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.4 (via coho)
|
||||
* Update JS snapshot to version 3.6.4 (via coho)
|
||||
* CB-7634 Detect JAVA_HOME properly on Ubuntu
|
||||
* CB-7579 Fix run script's ability to use non-arch-specific APKs
|
||||
* CB-6511 Fixes build for android when app name contains unicode characters.
|
||||
* 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
|
||||
|
||||
### 3.6.0 (Sept 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.0 (via coho)
|
||||
* CB-7410 fix the menu test
|
||||
* CB-7410 Fix the errorUrl test
|
||||
* CB-7410 Fix Basic Authentication test
|
||||
* CB-3445: Allow build and run scripts to select APK by architecture
|
||||
* CB-3445: Add environment variable 'BUILD_MULTIPLE_APKS' for splitting APKs based on architecture
|
||||
* CB-3445: Ensure that JAR files in libs directory are included
|
||||
* CB-7267 update RELEASENOTES for 3.5.1
|
||||
* CB-7410 clarify the title
|
||||
* CB-7385 update cordova.js for testing prior to branch/tag
|
||||
* CB-7410 add whitelist entries to get iframe/GoogleMaps working
|
||||
* CB-7291 propogate change in method signature to the native tests
|
||||
* CB-7291: Restrict meaning of "\*" in internal whitelist to just http and https
|
||||
* CB-7291: Only add file, content and data URLs to internal whitelist
|
||||
* CB-7291: Add defaults to external whitelist
|
||||
* CB-7291: Add external-launch-whitelist and use it for filtering intent launches
|
||||
* CB-3445: Read project.properties to configure gradle libraries
|
||||
* CB-7325 Fix error message in android_sdk_version.js when missing SDK on windows
|
||||
* CB-7335 Add a .gitignore to android project template
|
||||
* CB-7330 Fix dangling function call in last commit (broke gradle builds)
|
||||
* CB-7330 Don't run "android update" during creation
|
||||
* CB-3445 Add gradle support clean command (plus some code cleanup)
|
||||
* CB-7044 Fix typo in prev commit causing check_reqs to always fail.
|
||||
* CB-3445 Copy gradle wrapper in build instead of create
|
||||
* CB-3445 Add .gradle template files for "update" as well as "create"
|
||||
* CB-7044 Add JAVA_HOME when not set. Be stricter about ANDROID_HOME
|
||||
* CB-3445 Speed up gradle building (incremental builds go from 10s -> 1.5s for me)
|
||||
* CB-3445: android: Copy Gradle wrapper from Android SDK rather than bundling a JAR
|
||||
* CB-3445: Add which to checked-in node_modules
|
||||
* CB-3445: Add option to build and install with gradle
|
||||
* CB-3445: Add an initial set of Gradle build scripts
|
||||
* CB-7321 Don't require ant for create script
|
||||
* CB-7044, CB-7299 Fix up PATH problems when possible.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly. Forgot the manifest.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly
|
||||
* Adding tests related to 3.5.1
|
||||
* CB-7261 Fix setNativeToJsBridgeMode sometimes crashing when switching to ONLINE_EVENT
|
||||
* CB-7265 Fix crash when navigating to custom protocol (introduced in 3.5.1)
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* CB-7238: I should have collapsed this, but Config.init() must go before the creation of CordovaWebView
|
||||
* CB-7238: Minor band-aid to get tests running again, this has to go away before 3.6.0 is released, since this is an API change.
|
||||
* Extend whitelist to handle URLs without // chars
|
||||
* CB-7172 Force window to have focus after resume
|
||||
* CB-7159 Set background color of webView as well as its parent
|
||||
* CB-7018 Fix setButtonPlumbedToJs never un-listening
|
||||
* Undeprecate some just-deprecated symbols in PluginManager.
|
||||
* @Deprecate methods of PluginManager that were never meant to be public
|
||||
* Move plugin instantiation and instance storing logic PluginEntry->PluginManager
|
||||
* Fix broken unit test due to missing Config.init() call
|
||||
* Update to check for Google Glass APIs
|
||||
* Fix for `android` not being in PATH check on Windows
|
||||
* Displaying error when regex does not match.
|
||||
* Fix broken compile due to previous commit :(
|
||||
* Tweak CordovaPlugin.initialize method to be less deprecated.
|
||||
* Un-deprecate CordovaActivity.init() - it's needed to tweak prefs in onCreate
|
||||
* Tweak log messages in CordovaBridge with bridgeSecret is wrong
|
||||
* Backport CordovaBridge from 4.0.x -> master
|
||||
* Update unit tests to not use most deprecated things (e.g. DroidGap)
|
||||
* Add non-String overloades for CordovaPreferences.set()
|
||||
* Make CordovaWebview resilient to init() not being called (for backwards-compatibility)
|
||||
* Add node_module licenses to LICENSE
|
||||
* Update cordova.js snapshot to work with bridge changes
|
||||
* Provide CordovaPlugin with CordovaPreferences. Add new Plugin.initialize()
|
||||
* Convert usages of Config.\* to use the non-static versions
|
||||
* Change getProperty -> prefs.get\* within CordovaActivity
|
||||
* Make CordovaUriHelper class package-private
|
||||
* Fix PluginManager.setPluginEntries not removing old entries
|
||||
* Move registration of App plugin from config.xml -> code
|
||||
* Make setWebViewClient an override instead of an overload. Delete Location-change JS->Native bridge mode (missed some of it).
|
||||
* CB-4404 Revert setting android:windowSoftInputMode to "adjustPan"
|
||||
* Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init()
|
||||
* Deprecate some convenience methods on CordovaActivity
|
||||
* Fix CordovaPreferences not correctly parsing hex values (valueOf->decode)
|
||||
* Refactor: Move url-filter information into PluginEntry.
|
||||
* Don't re-parse config.xml in onResume.
|
||||
* Move handling of Fullscreen preference to CordovaActivity
|
||||
* Delete dead code from CordovaActivity
|
||||
* Update .classpath to make Eclipse happy (just re-orders one line)
|
||||
* Delete "CB-3064: The errorUrl is..." Log message left over from debugging presumably
|
||||
* Refactor Config into ConfigXmlParser, CordovaPreferences
|
||||
* Delete Location-change JS->Native bridge mode
|
||||
* CB-5988 Allow exec() only from file: or start-up URL's domain
|
||||
* CB-6761 Fix native->JS bridge ceasing to fire when page changes and online is set to false and the JS loads quickly
|
||||
* Update the errorurl to no longer use intents
|
||||
* This breaks running the JUnit tests, we'll bring it back soon
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
* CB-7018 Clean up and deprecation of some button-related functions
|
||||
* CB-7017 Fix onload=true being set on all subsequent plugins
|
||||
* CB-5971: Fix package / project validation
|
||||
* CB-5971: Add unit tests to cordova-android
|
||||
* CB-5971: Factor out package/project name validation logic
|
||||
* Delete explicit activity.finish() in back button handling. No change in behaviour.
|
||||
* CB-5971: This would have been a good first bug, too bad
|
||||
* CB-4404: Changing where android:windowSoftInputMode is in the manifest so it works
|
||||
* Add documentation referencing other implementation.
|
||||
* CB-6851 Deprecate WebView.sendJavascript()
|
||||
* CB-6876 Show the correct executable name
|
||||
* CB-6876 Fix the "print usage"
|
||||
* Trivial spelling fix in comments when reading CordovaResourceApi
|
||||
* CB-6818: I want to remove this code, because Square didn't do their headers properly
|
||||
* CB-6860 Add activity_name and launcher_name to AndroidManifest.xml & strings.xml
|
||||
* Add a comment to custom_rules.xml saying why we move AndroidManifest.xml
|
||||
* Remove +x from README.md
|
||||
* CB-6784 Add missing licenses
|
||||
* CB-6784 Add license to CONTRIBUTING.md
|
||||
* Revert "defaults.xml: Add AndroidLaunchMode preference"
|
||||
* updated RELEASENOTES
|
||||
* CB-6315: Wrapping this so it runs on the UI thread
|
||||
* CB-6723 Update package name for Robotium
|
||||
* CB-6707 Update minSdkVersion to 10 consistently
|
||||
* CB-5652 make visible cordova version
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Set VERSION to 3.6.0-dev (via coho)
|
||||
|
||||
### 3.5.1 (August 2014) ###
|
||||
|
||||
This was a security update to address CVE-2014-3500, CVE-2014-3501,
|
||||
and CVE-2014-3502. For more information, see
|
||||
http://cordova.apache.org/announcements/2014/08/04/android-351.html
|
||||
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* Update the errorurl to no longer use intents
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
|
||||
### 3.5.0 (May 2014) ###
|
||||
|
||||
* OkHttp has broken headers. Updating for ASF compliance.
|
||||
|
||||
@@ -51,7 +51,7 @@ get_sdks = function() {
|
||||
|
||||
return Q();
|
||||
}, function(stderr) {
|
||||
if (stderr.match(/command\snot\sfound/)) {
|
||||
if (stderr.match(/command\snot\sfound/) || stderr.match(/'android' is not recognized/)) {
|
||||
return Q.reject(new Error('The command \"android\" failed. Make sure you have the latest Android SDK installed, and the \"android\" command (inside the tools/ folder) is added to your path.'));
|
||||
} else {
|
||||
return Q.reject(new Error('An error occurred while listing Android targets'));
|
||||
|
||||
@@ -24,10 +24,19 @@ var shelljs = require('shelljs'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
which = require('which'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
var isWindows = process.platform == 'win32';
|
||||
|
||||
function forgivingWhichSync(cmd) {
|
||||
try {
|
||||
return which.sync(cmd);
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function tryCommand(cmd, errMsg) {
|
||||
var d = Q.defer();
|
||||
child_process.exec(cmd, function(err, stdout, stderr) {
|
||||
@@ -39,87 +48,180 @@ function tryCommand(cmd, errMsg) {
|
||||
|
||||
// Get valid target from framework/project.properties
|
||||
module.exports.get_target = function() {
|
||||
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.
|
||||
// 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'));
|
||||
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].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.
|
||||
module.exports.check_ant = function() {
|
||||
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.');
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_gradle = function() {
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||
if (!fs.existsSync(wrapperDir)) {
|
||||
return Q.reject(new Error('Could not find gradle wrapper within android sdk. Might need to update your Android SDK.\n' +
|
||||
'Looked here: ' + wrapperDir));
|
||||
}
|
||||
return Q.when();
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_java = function() {
|
||||
var javacInPath = !!shelljs.which('javac');
|
||||
var hasJavaHome = !!process.env.JAVA_HOME;
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (hasJavaHome && !javacInPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.JAVA_HOME, 'bin');
|
||||
} else if (isWindows && (!hasJavaHome || !javacInPath)) {
|
||||
// Try to auto-detect java in the default install paths.
|
||||
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];
|
||||
if (firstJdkDir) {
|
||||
// shelljs always uses / in paths.
|
||||
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
||||
if (!javacInPath) {
|
||||
process.env.PATH += path.delimiter + path.join(firstJdkDir, 'bin');
|
||||
var javacPath = forgivingWhichSync('javac');
|
||||
var hasJavaHome = !!process.env['JAVA_HOME'];
|
||||
return Q().then(function() {
|
||||
if (hasJavaHome) {
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (!javacPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
|
||||
}
|
||||
} else {
|
||||
if (javacPath) {
|
||||
// OS X has a command for finding JAVA_HOME.
|
||||
if (fs.existsSync('/usr/libexec/java_home')) {
|
||||
return tryCommand('/usr/libexec/java_home', 'Failed to run: /usr/libexec/java_home')
|
||||
.then(function(stdout) {
|
||||
process.env['JAVA_HOME'] = stdout.trim();
|
||||
});
|
||||
} else {
|
||||
// See if we can derive it from javac's location.
|
||||
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
||||
var maybeJavaHome = path.dirname(path.dirname(fs.realpathSync(javacPath)));
|
||||
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
||||
process.env['JAVA_HOME'] = maybeJavaHome;
|
||||
} else {
|
||||
throw new Error('Could not find JAVA_HOME. Try setting the environment variable manually');
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
if (!javacPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
|
||||
}
|
||||
process.env['JAVA_HOME'] = firstJdkDir;
|
||||
}
|
||||
}
|
||||
process.env.JAVA_HOME = firstJdkDir;
|
||||
}
|
||||
}
|
||||
var msg =
|
||||
'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() {
|
||||
msg = 'Failed to run "javac -version", make sure you have a Java JDK (not just a JRE) installed.';
|
||||
return tryCommand('javac -version', msg)
|
||||
}).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';
|
||||
}
|
||||
return tryCommand('java -version', msg)
|
||||
.then(function() {
|
||||
return tryCommand('javac -version', msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_android = function() {
|
||||
var androidCmdPath = !!shelljs.which('android');
|
||||
var adbInPath = !!shelljs.which('adb');
|
||||
var hasAndroidHome = !!process.env.ANDROID_HOME;
|
||||
if (hasAndroidHome && !androidCmdPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_HOME, 'tools');
|
||||
}
|
||||
if (androidCmdPath && !hasAndroidHome) {
|
||||
process.env.ANDROID_HOME = path.dirname(path.dirname(androidCmdPath));
|
||||
hasAndroidHome = true;
|
||||
}
|
||||
if (hasAndroidHome && !adbInPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_HOME, 'platform-tools');
|
||||
}
|
||||
return Q().then(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');
|
||||
}
|
||||
if (androidCmdPath && !hasAndroidHome) {
|
||||
var parentDir = path.dirname(androidCmdPath);
|
||||
if (path.basename(parentDir) == 'tools') {
|
||||
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
||||
hasAndroidHome = true;
|
||||
}
|
||||
}
|
||||
if (hasAndroidHome && !adbInPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
|
||||
}
|
||||
if (!process.env['ANDROID_HOME']) {
|
||||
throw new Error('ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.');
|
||||
}
|
||||
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
|
||||
throw new Error('ANDROID_HOME is set to a non-existant path: ' + process.env['ANDROID_HOME']);
|
||||
}
|
||||
// Check that the target sdk level is installed.
|
||||
return module.exports.check_android_target(module.exports.get_target());
|
||||
});
|
||||
};
|
||||
|
||||
var valid_target = this.get_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.';
|
||||
return tryCommand('android list targets', msg)
|
||||
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)
|
||||
.then(function(output) {
|
||||
if (!output.match(valid_target)) {
|
||||
return Q.reject(new Error('Please install Android target ' + valid_target.split('-')[1] +
|
||||
' (the Android newest SDK). Make sure you have the latest Android tools installed as well.' +
|
||||
' Run "android" from your command-line to install/update any missing SDKs or tools.'));
|
||||
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)');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.run = function() {
|
||||
|
||||
@@ -83,16 +83,46 @@ function copyJsAndLibrary(projectPath, shared, projectName) {
|
||||
}
|
||||
}
|
||||
|
||||
function runAndroidUpdate(projectPath, target_api, shared) {
|
||||
var targetFrameworkDir = getFrameworkDir(projectPath, shared);
|
||||
return exec('android update project --subprojects --path "' + projectPath + '" --target ' + target_api + ' --library "' + path.relative(projectPath, targetFrameworkDir) + '"');
|
||||
function extractSubProjectPaths(data) {
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg
|
||||
var m;
|
||||
while (m = r.exec(data)) {
|
||||
ret[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(ret);
|
||||
}
|
||||
|
||||
function copyAntRules(projectPath) {
|
||||
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
||||
if (fs.existsSync(path.join(srcDir, 'custom_rules.xml'))) {
|
||||
shell.cp('-f', path.join(srcDir, 'custom_rules.xml'), projectPath);
|
||||
function writeProjectProperties(projectPath, target_api, shared) {
|
||||
var dstPath = path.join(projectPath, 'project.properties');
|
||||
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
||||
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||
var data = fs.readFileSync(srcPath, 'utf8');
|
||||
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
||||
var subProjects = extractSubProjectPaths(data);
|
||||
subProjects = subProjects.filter(function(p) {
|
||||
return !(/^CordovaLib$/m.exec(p) ||
|
||||
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
|
||||
/^(\.\.[\\\/])+framework$/m.exec(p)
|
||||
);
|
||||
});
|
||||
subProjects.unshift(shared ? path.relative(projectPath, path.join(ROOT, 'framework')) : 'CordovaLib');
|
||||
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
|
||||
if (!/\n$/.exec(data)) {
|
||||
data += '\n';
|
||||
}
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
|
||||
}
|
||||
fs.writeFileSync(dstPath, data);
|
||||
}
|
||||
|
||||
function copyBuildRules(projectPath) {
|
||||
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
||||
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);
|
||||
}
|
||||
|
||||
function copyScripts(projectPath) {
|
||||
@@ -196,10 +226,6 @@ 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:');
|
||||
@@ -215,13 +241,7 @@ exports.createProject = function(project_path, package_name, project_name, proje
|
||||
shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
|
||||
shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
|
||||
shell.cp('-r', path.join(ROOT, 'framework', 'res', 'xml'), path.join(project_path, 'res'));
|
||||
|
||||
shell.cp('-f', path.join(project_template_dir, 'build.gradle'), project_path);
|
||||
shell.cp('-f', path.join(project_template_dir, 'libraries.gradle'), project_path);
|
||||
shell.cp('-f', path.join(project_template_dir, 'settings.gradle'), project_path);
|
||||
shell.cp('-f', path.join(project_template_dir, 'gradlew'), project_path);
|
||||
shell.cp('-f', path.join(project_template_dir, 'gradlew.bat'), project_path);
|
||||
shell.cp('-r', path.join(project_template_dir, 'gradle'), project_path);
|
||||
shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
|
||||
|
||||
// Manually create directories that would be empty within the template (since git doesn't track directories).
|
||||
shell.mkdir(path.join(project_path, 'libs'));
|
||||
@@ -253,10 +273,10 @@ exports.createProject = function(project_path, package_name, project_name, proje
|
||||
shell.sed('-i', /__PACKAGE__/, package_name, manifest_path);
|
||||
shell.sed('-i', /__APILEVEL__/, target_api.split('-')[1], manifest_path);
|
||||
copyScripts(project_path);
|
||||
copyAntRules(project_path);
|
||||
copyBuildRules(project_path);
|
||||
});
|
||||
// Link it to local android install.
|
||||
return runAndroidUpdate(project_path, target_api, use_shared_project);
|
||||
writeProjectProperties(project_path, target_api);
|
||||
}).then(function() {
|
||||
console.log('Project successfully created.');
|
||||
});
|
||||
@@ -279,22 +299,19 @@ function extractProjectNameFromManifest(projectPath) {
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
exports.updateProject = function(projectPath) {
|
||||
var version = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
||||
// Check that requirements are met and proper targets are installed
|
||||
return check_reqs.run()
|
||||
exports.updateProject = function(projectPath, shared) {
|
||||
var newVersion = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
||||
return Q()
|
||||
.then(function() {
|
||||
var projectName = extractProjectNameFromManifest(projectPath);
|
||||
var target_api = check_reqs.get_target();
|
||||
copyJsAndLibrary(projectPath, false, projectName);
|
||||
copyJsAndLibrary(projectPath, shared, projectName);
|
||||
copyScripts(projectPath);
|
||||
copyAntRules(projectPath);
|
||||
copyBuildRules(projectPath);
|
||||
removeDebuggableFromManifest(projectPath);
|
||||
return runAndroidUpdate(projectPath, target_api, false)
|
||||
.then(function() {
|
||||
console.log('Android project is now at version ' + version);
|
||||
console.log('If you updated from a pre-3.2.0 version and use an IDE, we now require that you import the "CordovaLib" library project.');
|
||||
});
|
||||
writeProjectProperties(projectPath, target_api, shared);
|
||||
console.log('Android project is now at version ' + newVersion);
|
||||
console.log('If you updated from a pre-3.2.0 version and use an IDE, we now require that you import the "CordovaLib" library project.');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ if(args[2] == '--help' ||
|
||||
build.help();
|
||||
} else {
|
||||
reqs.run().done(function() {
|
||||
return build.run.call(build.run, args.slice(2));
|
||||
return build.run(args.slice(2));
|
||||
}, function(err) {
|
||||
console.error(err);
|
||||
process.exit(2);
|
||||
|
||||
@@ -19,18 +19,26 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var clean = require('./lib/clean'),
|
||||
var build = require('./lib/build'),
|
||||
reqs = require('./lib/check_reqs'),
|
||||
args = process.argv;
|
||||
var path = require('path');
|
||||
|
||||
// Usage support for when args are given
|
||||
if(args.length > 2) {
|
||||
clean.help();
|
||||
// Support basic help commands
|
||||
if(args[2] == '--help' ||
|
||||
args[2] == '/?' ||
|
||||
args[2] == '-h' ||
|
||||
args[2] == 'help' ||
|
||||
args[2] == '-help' ||
|
||||
args[2] == '/help') {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
||||
console.log('Cleans the project directory.');
|
||||
process.exit(0);
|
||||
} else {
|
||||
reqs.run().done(function() {
|
||||
return clean.run();
|
||||
return build.runClean(args.slice(2));
|
||||
}, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
console.error(err);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
|
||||
434
bin/templates/cordova/lib/build.js
vendored
434
bin/templates/cordova/lib/build.js
vendored
@@ -26,32 +26,86 @@ var shell = require('shelljs'),
|
||||
fs = require('fs'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
var check_reqs = require('./check_reqs');
|
||||
var exec = require('./exec');
|
||||
|
||||
// Globals
|
||||
var build_type,
|
||||
build_method;
|
||||
var LOCAL_PROPERTIES_TEMPLATE =
|
||||
'# This file is automatically generated.\n' +
|
||||
'# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n';
|
||||
|
||||
function find_files(directory, predicate) {
|
||||
function findApks(directory) {
|
||||
var ret = [];
|
||||
if (fs.existsSync(directory)) {
|
||||
var candidates = fs.readdirSync(directory).filter(predicate).map(function(p) {
|
||||
p = path.join(directory, p);
|
||||
return { p: p, t: fs.statSync(p).mtime };
|
||||
}).sort(function(a,b) {
|
||||
return a.t > b.t ? -1 :
|
||||
a.t < b.t ? 1 : 0;
|
||||
}).map(function(p) { return p.p; });
|
||||
return candidates;
|
||||
} else {
|
||||
console.error('ERROR : unable to find project ' + directory + ' directory, could not locate .apk');
|
||||
process.exit(2);
|
||||
fs.readdirSync(directory).forEach(function(p) {
|
||||
if (path.extname(p) == '.apk') {
|
||||
ret.push(path.join(directory, p));
|
||||
}
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function sortFilesByDate(files) {
|
||||
return files.map(function(p) {
|
||||
return { p: p, t: fs.statSync(p).mtime };
|
||||
}).sort(function(a, b) {
|
||||
var timeDiff = b.t - a.t;
|
||||
return timeDiff === 0 ? a.p.length - b.p.length : timeDiff;
|
||||
}).map(function(p) { return p.p; });
|
||||
}
|
||||
|
||||
function findOutputApksHelper(dir, build_type, arch) {
|
||||
var ret = findApks(dir).filter(function(candidate) {
|
||||
// Need to choose between release and debug .apk.
|
||||
if (build_type === 'debug') {
|
||||
return /-debug/.exec(candidate) && !/-unaligned|-unsigned/.exec(candidate);
|
||||
}
|
||||
if (build_type === 'release') {
|
||||
return /-release/.exec(candidate) && !/-unaligned/.exec(candidate);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
ret = sortFilesByDate(ret);
|
||||
if (ret.length === 0) {
|
||||
return ret;
|
||||
}
|
||||
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
|
||||
ret = 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() {
|
||||
return fs.existsSync(path.join(ROOT, 'custom_rules.xml'));
|
||||
}
|
||||
|
||||
module.exports.builders = {
|
||||
function extractProjectNameFromManifest(projectPath) {
|
||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new Error('Could not find activity name in ' + manifestPath);
|
||||
}
|
||||
return m[1];
|
||||
}
|
||||
|
||||
function extractSubProjectPaths() {
|
||||
var data = fs.readFileSync(path.join(ROOT, 'project.properties'), 'utf8');
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg
|
||||
var m;
|
||||
while (m = r.exec(data)) {
|
||||
ret[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(ret);
|
||||
}
|
||||
|
||||
var builders = {
|
||||
ant: {
|
||||
getArgs: function(cmd) {
|
||||
var args = [cmd, '-f', path.join(ROOT, 'build.xml')];
|
||||
@@ -59,118 +113,233 @@ module.exports.builders = {
|
||||
if (hasCustomRules()) {
|
||||
args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
|
||||
}
|
||||
try {
|
||||
// Specify sdk dir in case local properties are missing
|
||||
args.push('-Dsdk.dir='+path.join(which.sync('android'), '../..'));
|
||||
} catch(e) {
|
||||
// Can't find android; don't push arg: assume all is okay
|
||||
}
|
||||
return args;
|
||||
},
|
||||
|
||||
prepEnv: function() {
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
// Copy in build.xml on each build so that:
|
||||
// A) we don't require the Android SDK at project creation time, and
|
||||
// B) we always use the SDK's latest version of it.
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
|
||||
function writeBuildXml(projectPath) {
|
||||
var newData = buildTemplate.replace('PROJECT_NAME', extractProjectNameFromManifest(ROOT));
|
||||
fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
|
||||
if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
|
||||
fs.writeFileSync(path.join(projectPath, 'local.properties'), LOCAL_PROPERTIES_TEMPLATE);
|
||||
}
|
||||
}
|
||||
var subProjects = extractSubProjectPaths();
|
||||
writeBuildXml(ROOT);
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
writeBuildXml(path.join(ROOT, subProjects[i]));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Builds the project with ant.
|
||||
* Returns a promise.
|
||||
*/
|
||||
build: function(build_type) {
|
||||
// Without our custom_rules.xml, we need to clean before building.
|
||||
var ret = Q();
|
||||
if (!hasCustomRules()) {
|
||||
// clean will call check_ant() for us.
|
||||
ret = this.clean();
|
||||
}
|
||||
|
||||
var builder = this;
|
||||
var args = builder.getArgs(build_type == "debug" ? 'debug' : 'release');
|
||||
return Q().then(function() {
|
||||
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release');
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args);
|
||||
}).then(function() {
|
||||
return builder.getOutputFiles();
|
||||
});
|
||||
},
|
||||
|
||||
// Find the recently-generated output APK files
|
||||
// Ant only generates one output file; return it.
|
||||
getOutputFiles: function() {
|
||||
var binDir;
|
||||
if(hasCustomRules()) {
|
||||
binDir = path.join(ROOT, 'ant-build');
|
||||
} else {
|
||||
binDir = path.join(ROOT, 'bin');
|
||||
}
|
||||
var candidates = find_files(binDir, function(candidate) { return path.extname(candidate) == '.apk'; });
|
||||
if (candidates.length === 0) {
|
||||
console.error('ERROR : No .apk found in ' + binDir + ' directory');
|
||||
process.exit(2);
|
||||
}
|
||||
console.log('Using apk: ' + candidates[0]);
|
||||
return [candidates[0]];
|
||||
clean: function() {
|
||||
var args = this.getArgs('clean');
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args);
|
||||
});
|
||||
},
|
||||
|
||||
findOutputApks: function(build_type) {
|
||||
var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
|
||||
return findOutputApksHelper(binDir, build_type, null);
|
||||
}
|
||||
},
|
||||
gradle: {
|
||||
getArgs: function(cmd) {
|
||||
getArgs: function(cmd, arch) {
|
||||
var lintSteps;
|
||||
if (process.env['BUILD_MULTIPLE_APKS']) {
|
||||
lintSteps = [
|
||||
'lint',
|
||||
'lintVitalX86Release',
|
||||
'lintVitalArmv7Release',
|
||||
'compileLint',
|
||||
'copyReleaseLint',
|
||||
'copyDebugLint'
|
||||
];
|
||||
} else {
|
||||
lintSteps = [
|
||||
'lint',
|
||||
'lintVitalRelease',
|
||||
'compileLint',
|
||||
'copyReleaseLint',
|
||||
'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');
|
||||
// Excluding lint: 6s-> 1.6s
|
||||
for (var i = 0; i < lintSteps.length; ++i) {
|
||||
args.push('-x', lintSteps[i]);
|
||||
}
|
||||
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
|
||||
// args.push('-Dorg.gradle.parallel=true');
|
||||
return args;
|
||||
},
|
||||
|
||||
prepEnv: function() {
|
||||
return check_reqs.check_gradle()
|
||||
.then(function() {
|
||||
// Copy the gradle wrapper on each build so that:
|
||||
// A) we don't require the Android SDK at project creation time, and
|
||||
// B) we always use the SDK's latest version of it.
|
||||
var projectPath = ROOT;
|
||||
// check_reqs ensures that this is set.
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||
if (process.platform == 'win32') {
|
||||
shell.cp('-f', path.join(wrapperDir, 'gradlew.bat'), projectPath);
|
||||
} else {
|
||||
shell.cp('-f', path.join(wrapperDir, 'gradlew'), projectPath);
|
||||
}
|
||||
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);
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Builds the project with gradle.
|
||||
* Returns a promise.
|
||||
*/
|
||||
build: function(build_type) {
|
||||
build: function(build_type, arch) {
|
||||
var builder = this;
|
||||
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 spawn(wrapper, args);
|
||||
}).then(function() {
|
||||
return builder.getOutputFiles(build_type);
|
||||
});
|
||||
},
|
||||
|
||||
// Find the recently-generated output APK files
|
||||
// Gradle can generate multiple output files; return all of them.
|
||||
getOutputFiles: function(build_type) {
|
||||
var binDir = path.join(ROOT, 'build', 'apk');
|
||||
var candidates = find_files(binDir, function(candidate) {
|
||||
// Need to choose between release and debug .apk.
|
||||
if (build_type === 'debug') {
|
||||
return (path.extname(candidate) == '.apk' && candidate.indexOf('-debug-') >= 0);
|
||||
}
|
||||
if (build_type === 'release') {
|
||||
return (path.extname(candidate) == '.apk' && candidate.indexOf('-release-') >= 0);
|
||||
}
|
||||
return path.extname(candidate) == '.apk';
|
||||
clean: function() {
|
||||
var builder = this;
|
||||
var wrapper = path.join(ROOT, 'gradlew');
|
||||
var args = builder.getArgs('clean');
|
||||
return Q().then(function() {
|
||||
return spawn(wrapper, args);
|
||||
});
|
||||
return candidates;
|
||||
},
|
||||
|
||||
findOutputApks: function(build_type, arch) {
|
||||
var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
|
||||
return findOutputApksHelper(binDir, build_type, arch);
|
||||
}
|
||||
},
|
||||
|
||||
none: {
|
||||
prepEnv: function() {
|
||||
return Q();
|
||||
},
|
||||
build: function() {
|
||||
console.log('Skipping build...');
|
||||
return Q(null);
|
||||
},
|
||||
clean: function() {
|
||||
return Q();
|
||||
},
|
||||
findOutputApks: function(build_type, arch) {
|
||||
return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function(options) {
|
||||
|
||||
function parseOpts(options, resolvedTarget) {
|
||||
// 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
|
||||
};
|
||||
|
||||
// Iterate through command line options
|
||||
for (var i=0; options && (i < options.length); ++i) {
|
||||
if (options[i].substring && options[i].substring(0,2) == "--") {
|
||||
if (/^--/.exec(options[i])) {
|
||||
var option = options[i].substring(2);
|
||||
switch(option) {
|
||||
case 'debug':
|
||||
case 'release':
|
||||
if (build_type) {
|
||||
return Q.reject('Multiple build types (' + build_type + ' and ' + option + ') specified.');
|
||||
}
|
||||
build_type = option;
|
||||
ret.buildType = option;
|
||||
break;
|
||||
case 'ant':
|
||||
case 'gradle':
|
||||
if (build_method) {
|
||||
return Q.reject('Multiple build methods (' + build_method + ' and ' + option + ') specified.');
|
||||
}
|
||||
build_method = option;
|
||||
ret.buildMethod = option;
|
||||
break;
|
||||
case 'nobuild' :
|
||||
console.log('Skipping build...');
|
||||
return Q();
|
||||
ret.buildMethod = 'none';
|
||||
break;
|
||||
default :
|
||||
return Q.reject('Build option \'' + options[i] + '\' not recognized.');
|
||||
}
|
||||
@@ -178,54 +347,85 @@ module.exports.run = function(options) {
|
||||
return Q.reject('Build option \'' + options[i] + '\' not recognized.');
|
||||
}
|
||||
}
|
||||
// Defaults
|
||||
build_type = build_type || "debug";
|
||||
build_method = build_method || process.env.ANDROID_BUILD || "ant";
|
||||
|
||||
// Get the builder
|
||||
var builder = module.exports.builders[build_method];
|
||||
|
||||
// Without our custom_rules.xml, we need to clean before building.
|
||||
var ret;
|
||||
if (!hasCustomRules()) {
|
||||
// clean will call check_ant() for us.
|
||||
ret = require('./clean').run();
|
||||
} else {
|
||||
ret = check_reqs.check_ant();
|
||||
var multiApk = ret.buildMethod == 'gradle' && process.env['BUILD_MULTIPLE_APKS'];
|
||||
if (multiApk && !/0|false|no/i.exec(multiApk)) {
|
||||
ret.arch = resolvedTarget && resolvedTarget.arch;
|
||||
}
|
||||
|
||||
// Return a promise for the actual build
|
||||
return ret.then(function() {
|
||||
return builder.build.call(builder, build_type);
|
||||
}).then(function(apkFiles) {
|
||||
var outputDir = path.join(ROOT, 'out');
|
||||
try {
|
||||
fs.mkdirSync(outputDir);
|
||||
} catch (e) {
|
||||
if (e.code != "EEXIST") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
for (var i=0; i < apkFiles.length; ++i) {
|
||||
shell.cp('-f', apkFiles[i], path.join(outputDir, path.basename(apkFiles[i])));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.runClean = function(options) {
|
||||
var opts = parseOpts(options);
|
||||
var builder = builders[opts.buildMethod];
|
||||
return builder.prepEnv()
|
||||
.then(function() {
|
||||
return builder.clean();
|
||||
}).then(function() {
|
||||
shell.rm('-rf', path.join(ROOT, 'out'));
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets the path to the apk file, if not such file exists then
|
||||
* the script will error out. (should we error or just return undefined?)
|
||||
* This is called by the run script to install the apk to the device
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.get_apk = function(build_type) {
|
||||
var outputDir = path.join(ROOT, 'out');
|
||||
var candidates = find_files(outputDir, function() { return true; });
|
||||
if (candidates.length === 0) {
|
||||
console.error('ERROR : No .apk found in ' + outputDir + ' directory');
|
||||
process.exit(2);
|
||||
module.exports.run = function(options, optResolvedTarget) {
|
||||
var opts = parseOpts(options, optResolvedTarget);
|
||||
var builder = builders[opts.buildMethod];
|
||||
return builder.prepEnv()
|
||||
.then(function() {
|
||||
return builder.build(opts.buildType, opts.arch);
|
||||
}).then(function() {
|
||||
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
|
||||
console.log('Built the following apk(s):');
|
||||
console.log(' ' + apkPaths.join('\n '));
|
||||
return {
|
||||
apkPaths: apkPaths,
|
||||
buildType: opts.buildType,
|
||||
buildMethod: opts.buildMethod
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Detects the architecture of a device/emulator
|
||||
* Returns "arm" or "x86".
|
||||
*/
|
||||
module.exports.detectArchitecture = function(target) {
|
||||
return exec('adb -s ' + target + ' shell cat /proc/cpuinfo')
|
||||
.then(function(output) {
|
||||
if (/intel/i.exec(output)) {
|
||||
return 'x86';
|
||||
}
|
||||
return 'arm';
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.findBestApkForArchitecture = function(buildResults, arch) {
|
||||
var paths = buildResults.apkPaths.filter(function(p) {
|
||||
if (buildResults.buildType == 'debug') {
|
||||
return /-debug/.exec(p);
|
||||
}
|
||||
return !/-debug/.exec(p);
|
||||
});
|
||||
var archPattern = new RegExp('-' + arch);
|
||||
var hasArchPattern = /-x86|-arm/;
|
||||
for (var i = 0; i < paths.length; ++i) {
|
||||
if (hasArchPattern.exec(paths[i])) {
|
||||
if (archPattern.exec(paths[i])) {
|
||||
return paths[i];
|
||||
}
|
||||
} else {
|
||||
return paths[i];
|
||||
}
|
||||
}
|
||||
console.log('Using apk: ' + candidates[0]);
|
||||
return candidates[0];
|
||||
throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
|
||||
};
|
||||
|
||||
module.exports.help = function() {
|
||||
|
||||
43
bin/templates/cordova/lib/clean.js
vendored
43
bin/templates/cordova/lib/clean.js
vendored
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var build = require('./build'),
|
||||
spawn = require('./spawn'),
|
||||
path = require('path');
|
||||
var check_reqs = require('./check_reqs');
|
||||
|
||||
/*
|
||||
* Cleans the project using ant
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function() {
|
||||
var args = build.getAntArgs('clean');
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.help = function() {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
||||
console.log('Cleans the project directory.');
|
||||
process.exit(0);
|
||||
}
|
||||
80
bin/templates/cordova/lib/device.js
vendored
80
bin/templates/cordova/lib/device.js
vendored
@@ -43,44 +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
|
||||
* and launches it.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.install = function(target) {
|
||||
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.');
|
||||
|
||||
// default device
|
||||
target = typeof target !== 'undefined' ? target : device_list[0];
|
||||
|
||||
if (device_list.indexOf(target) < 0)
|
||||
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
||||
|
||||
var apk_path = build.get_apk();
|
||||
launchName = appinfo.getActivityName();
|
||||
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 ' + 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 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);
|
||||
|
||||
//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);
|
||||
//unlock screen
|
||||
var cmd = 'adb -s ' + resolvedTarget.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 ' + 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
97
bin/templates/cordova/lib/emulator.js
vendored
97
bin/templates/cordova/lib/emulator.js
vendored
@@ -28,6 +28,7 @@ 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
|
||||
@@ -84,7 +85,7 @@ module.exports.list_images = function() {
|
||||
* Returns a promise.
|
||||
*/
|
||||
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()
|
||||
.then(function(images) {
|
||||
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.
|
||||
module.exports.list_targets = function() {
|
||||
return exec('android list targets')
|
||||
@@ -156,7 +152,7 @@ module.exports.start = function(emulator_ID) {
|
||||
.then(function(list) {
|
||||
started_emulators = list;
|
||||
num_started = started_emulators.length;
|
||||
if (typeof emulator_ID === 'undefined') {
|
||||
if (!emulator_ID) {
|
||||
return self.list_images()
|
||||
.then(function(emulator_list) {
|
||||
if (emulator_list.length > 0) {
|
||||
@@ -167,11 +163,11 @@ module.exports.start = function(emulator_ID) {
|
||||
return emulator_ID;
|
||||
});
|
||||
} else {
|
||||
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.');
|
||||
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');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -277,14 +273,7 @@ module.exports.create_image = function(name, 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) {
|
||||
var self = this;
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list_started()
|
||||
.then(function(emulator_list) {
|
||||
if (emulator_list.length < 1) {
|
||||
@@ -292,33 +281,55 @@ module.exports.install = function(target) {
|
||||
}
|
||||
|
||||
// default emulator
|
||||
target = typeof target !== 'undefined' ? target : emulator_list[0];
|
||||
target = target || emulator_list[0];
|
||||
if (emulator_list.indexOf(target) < 0) {
|
||||
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
||||
}
|
||||
|
||||
console.log('Installing app on emulator...');
|
||||
var apk_path = build.get_apk();
|
||||
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);
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return {target:target, arch:arch, isEmulator:true};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* 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();
|
||||
}, 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);
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
63
bin/templates/cordova/lib/plugin-build.gradle
Normal file
63
bin/templates/cordova/lib/plugin-build.gradle
Normal file
@@ -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'
|
||||
}
|
||||
117
bin/templates/cordova/lib/run.js
vendored
117
bin/templates/cordova/lib/run.js
vendored
@@ -33,16 +33,16 @@ var path = require('path'),
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function(args) {
|
||||
var build_type;
|
||||
var buildFlags = [];
|
||||
var install_target;
|
||||
|
||||
for (var i=2; i<args.length; i++) {
|
||||
if (args[i] == '--debug') {
|
||||
build_type = '--debug';
|
||||
buildFlags.push('--debug');
|
||||
} else if (args[i] == '--release') {
|
||||
build_type = '--release';
|
||||
buildFlags.push('--release');
|
||||
} else if (args[i] == '--nobuild') {
|
||||
build_type = '--nobuild';
|
||||
buildFlags.push('--nobuild');
|
||||
} else if (args[i] == '--device') {
|
||||
install_target = '--device';
|
||||
} else if (args[i] == '--emulator') {
|
||||
@@ -55,73 +55,66 @@ var path = require('path'),
|
||||
}
|
||||
}
|
||||
|
||||
return build.run(build_type).then(function() {
|
||||
if (install_target == '--device') {
|
||||
return device.install();
|
||||
} 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() { emulator.install(); });
|
||||
});
|
||||
} 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);
|
||||
} else if (started_emulators.indexOf(install_target) > -1) {
|
||||
return emulator.install(install_target);
|
||||
} 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); });
|
||||
}
|
||||
}
|
||||
return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Q()
|
||||
.then(function() {
|
||||
if (!install_target) {
|
||||
// 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] + '\'.');
|
||||
return device.install(device_list[0]);
|
||||
install_target = device_list[0];
|
||||
} else {
|
||||
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]);
|
||||
} 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);
|
||||
});
|
||||
} else {
|
||||
return emulator.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
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 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:
|
||||
var VERSION = "3.6.0-dev";
|
||||
var VERSION = "3.7.0-dev";
|
||||
|
||||
console.log(VERSION);
|
||||
|
||||
@@ -28,6 +28,7 @@ public class __ACTIVITY__ extends CordovaActivity
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
super.init();
|
||||
// Set by <content src="index.html" /> in config.xml
|
||||
loadUrl(launchUrl);
|
||||
}
|
||||
|
||||
@@ -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:hardwareAccelerated="true" android:supportsRtl="true">
|
||||
<activity android:name="__ACTIVITY__"
|
||||
android:label="@string/activity_name"
|
||||
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'
|
||||
|
||||
buildscript {
|
||||
@@ -8,16 +32,15 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.10.+'
|
||||
classpath 'com.android.tools.build:gradle:0.12.0+'
|
||||
}
|
||||
}
|
||||
|
||||
ext.multiarch=false
|
||||
|
||||
dependencies {
|
||||
compile project(':CordovaLib')
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.12'
|
||||
}
|
||||
apply from: 'libraries.gradle'
|
||||
|
||||
ext.multiarch=false
|
||||
|
||||
android {
|
||||
sourceSets {
|
||||
@@ -33,13 +56,13 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionCode Integer.parseInt("" + getVersionCodeFromManifest() + "0")
|
||||
versionCode Integer.parseInt(System.env.ANDROID_VERSION_CODE ?: ("" + getVersionCodeFromManifest() + "0"))
|
||||
}
|
||||
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "19.0.0"
|
||||
compileSdkVersion cordova.cordovaSdkVersion
|
||||
buildToolsVersion cordova.cordovaBuildToolsVersion
|
||||
|
||||
if (multiarch) {
|
||||
if (multiarch || System.env.BUILD_MULTIPLE_APKS) {
|
||||
productFlavors {
|
||||
armv7 {
|
||||
versionCode defaultConfig.versionCode + 2
|
||||
@@ -66,10 +89,78 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.12'
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getVersionCodeFromManifest() {
|
||||
@@ -79,3 +170,26 @@ def getVersionCodeFromManifest() {
|
||||
matcher.find()
|
||||
return Integer.parseInt(matcher.group(1))
|
||||
}
|
||||
|
||||
def ensureValueExists(filePath, props, key) {
|
||||
if (props.get(key) == null) {
|
||||
throw new GradleException(filePath + ': Missing key required "' + key + '"')
|
||||
}
|
||||
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'
|
||||
}
|
||||
|
||||
120
bin/templates/project/cordova.gradle
Normal file
120
bin/templates/project/cordova.gradle
Normal file
@@ -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")
|
||||
|
||||
14
bin/templates/project/gitignore
Normal file
14
bin/templates/project/gitignore
Normal file
@@ -0,0 +1,14 @@
|
||||
# Non-project-specific build files:
|
||||
build.xml
|
||||
local.properties
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/gradle
|
||||
# Ant builds
|
||||
ant-built
|
||||
ant-gen
|
||||
# Eclipse builds
|
||||
gen
|
||||
out
|
||||
# Gradle builds
|
||||
/build
|
||||
@@ -1,6 +0,0 @@
|
||||
#Fri Jun 13 09:52:43 EDT 2014
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
|
||||
164
bin/templates/project/gradlew
vendored
164
bin/templates/project/gradlew
vendored
@@ -1,164 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
bin/templates/project/gradlew.bat
vendored
90
bin/templates/project/gradlew.bat
vendored
@@ -1,90 +0,0 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,7 +0,0 @@
|
||||
dependencies {
|
||||
// This file contains no plugins by default.
|
||||
// To add a third-party library project, add a line to this file like
|
||||
// compile project(':library_dir_name')
|
||||
}
|
||||
// If multiple ndk architectures are provided, uncomment this line
|
||||
//ext.multiarch=true
|
||||
15
bin/templates/project/project.properties
Normal file
15
bin/templates/project/project.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
android.library.reference.1=CordovaLib
|
||||
# Project target.
|
||||
target=This_gets_replaced
|
||||
@@ -1 +0,0 @@
|
||||
include ':CordovaLib', ':'
|
||||
57
framework/assets/www/cordova.js
vendored
57
framework/assets/www/cordova.js
vendored
@@ -1,5 +1,5 @@
|
||||
// Platform: android
|
||||
// 3.6.0-dev-70cdca3
|
||||
// 8ca0f3b2b87e0759c5236b91c80f18438544409c
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
@@ -19,7 +19,7 @@
|
||||
under the License.
|
||||
*/
|
||||
;(function() {
|
||||
var CORDOVA_JS_BUILD_LABEL = '3.6.0-dev-70cdca3';
|
||||
var PLATFORM_VERSION_BUILD_LABEL = '3.7.0-dev';
|
||||
// file: src/scripts/require.js
|
||||
|
||||
/*jshint -W079 */
|
||||
@@ -175,7 +175,8 @@ function createEvent(type, data) {
|
||||
var cordova = {
|
||||
define:define,
|
||||
require:require,
|
||||
version:CORDOVA_JS_BUILD_LABEL,
|
||||
version:PLATFORM_VERSION_BUILD_LABEL,
|
||||
platformVersion:PLATFORM_VERSION_BUILD_LABEL,
|
||||
platformId:platform.id,
|
||||
/**
|
||||
* Methods to add/remove your own addEventListener hijacking on document + window.
|
||||
@@ -1183,6 +1184,16 @@ function replaceNavigator(origNavigator) {
|
||||
for (var key in origNavigator) {
|
||||
if (typeof origNavigator[key] == 'function') {
|
||||
newNavigator[key] = origNavigator[key].bind(origNavigator);
|
||||
} else {
|
||||
(function(k) {
|
||||
Object.defineProperty(newNavigator, k, {
|
||||
get: function() {
|
||||
return origNavigator[k];
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
})(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1302,6 +1313,16 @@ function replaceNavigator(origNavigator) {
|
||||
for (var key in origNavigator) {
|
||||
if (typeof origNavigator[key] == 'function') {
|
||||
newNavigator[key] = origNavigator[key].bind(origNavigator);
|
||||
} else {
|
||||
(function(k) {
|
||||
Object.defineProperty(newNavigator, k, {
|
||||
get: function() {
|
||||
return origNavigator[k];
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
})(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1497,6 +1518,17 @@ module.exports = {
|
||||
cordova.addDocumentEventHandler('menubutton');
|
||||
cordova.addDocumentEventHandler('searchbutton');
|
||||
|
||||
function bindButtonChannel(buttonName) {
|
||||
// generic button bind used for volumeup/volumedown buttons
|
||||
var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
|
||||
volumeButtonChannel.onHasSubscribersChange = function() {
|
||||
exec(null, null, "App", "overrideButton", [buttonName, this.numHandlers == 1]);
|
||||
};
|
||||
}
|
||||
// Inject a listener for the volume buttons on the document.
|
||||
bindButtonChannel('volumeup');
|
||||
bindButtonChannel('volumedown');
|
||||
|
||||
// Let native code know we are all done on the JS side.
|
||||
// Native code will then un-hide the WebView.
|
||||
channel.onCordovaReady.subscribe(function() {
|
||||
@@ -1574,6 +1606,21 @@ module.exports = {
|
||||
exec(null, null, "App", "overrideBackbutton", [override]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Override the default behavior of the Android volume button.
|
||||
* If overridden, when the volume button is pressed, the "volume[up|down]button"
|
||||
* JavaScript event will be fired.
|
||||
*
|
||||
* Note: The user should not have to call this method. Instead, when the user
|
||||
* registers for the "volume[up|down]button" event, this is automatically done.
|
||||
*
|
||||
* @param button volumeup, volumedown
|
||||
* @param override T=override, F=cancel override
|
||||
*/
|
||||
overrideButton:function(button, override) {
|
||||
exec(null, null, "App", "overrideButton", [button, override]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Exit and terminate the application.
|
||||
*/
|
||||
@@ -1667,11 +1714,11 @@ function handlePluginsObject(path, moduleList, finishPluginLoading) {
|
||||
function findCordovaPath() {
|
||||
var path = null;
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
var term = 'cordova.js';
|
||||
var term = '/cordova.js';
|
||||
for (var n = scripts.length-1; n>-1; n--) {
|
||||
var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
|
||||
if (src.indexOf(term) == (src.length - term.length)) {
|
||||
path = src.substring(0, src.length - term.length);
|
||||
path = src.substring(0, src.length - term.length) + '/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,48 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
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'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "19.0.0"
|
||||
compileSdkVersion cordova.cordovaSdkVersion
|
||||
buildToolsVersion cordova.cordovaBuildToolsVersion
|
||||
publishNonDefault true
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
|
||||
@@ -30,7 +30,20 @@
|
||||
Apache Cordova Team
|
||||
</author>
|
||||
|
||||
<access origin="*"/>
|
||||
<!-- Allow access to arbitrary URLs in the Cordova WebView. This is a
|
||||
development mode setting, and should be changed for production. -->
|
||||
<access origin="http://*/*"/>
|
||||
<access origin="https://*/*"/>
|
||||
|
||||
<!-- Grant certain URLs the ability to launch external applications. This
|
||||
behaviour is set to match that of Cordova versions before 3.6.0, and
|
||||
should be reviewed before launching an application in production. It
|
||||
may be changed in the future. -->
|
||||
<access origin="tel:*" launch-external="yes"/>
|
||||
<access origin="geo:*" launch-external="yes"/>
|
||||
<access origin="mailto:*" launch-external="yes"/>
|
||||
<access origin="sms:*" launch-external="yes"/>
|
||||
<access origin="market:*" launch-external="yes"/>
|
||||
|
||||
<!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
|
||||
<content src="index.html" />
|
||||
|
||||
@@ -58,7 +58,7 @@ public class Config {
|
||||
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||
return;
|
||||
}
|
||||
parser.getWhitelist().addWhiteListEntry(origin, subdomains);
|
||||
parser.getInternalWhitelist().addWhiteListEntry(origin, subdomains);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,21 @@ public class Config {
|
||||
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||
return false;
|
||||
}
|
||||
return parser.getWhitelist().isUrlWhiteListed(url);
|
||||
return parser.getInternalWhitelist().isUrlWhiteListed(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if URL is in approved list of URLs to launch external applications.
|
||||
*
|
||||
* @param url
|
||||
* @return true if whitelisted
|
||||
*/
|
||||
public static boolean isUrlExternallyWhiteListed(String url) {
|
||||
if (parser == null) {
|
||||
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||
return false;
|
||||
}
|
||||
return parser.getExternalWhitelist().isUrlWhiteListed(url);
|
||||
}
|
||||
|
||||
public static String getStartUrl() {
|
||||
@@ -87,7 +101,11 @@ public class Config {
|
||||
}
|
||||
|
||||
public static Whitelist getWhitelist() {
|
||||
return parser.getWhitelist();
|
||||
return parser.getInternalWhitelist();
|
||||
}
|
||||
|
||||
public static Whitelist getExternalWhitelist() {
|
||||
return parser.getExternalWhitelist();
|
||||
}
|
||||
|
||||
public static List<PluginEntry> getPluginEntries() {
|
||||
|
||||
@@ -37,11 +37,16 @@ public class ConfigXmlParser {
|
||||
|
||||
private String launchUrl = "file:///android_asset/www/index.html";
|
||||
private CordovaPreferences prefs = new CordovaPreferences();
|
||||
private Whitelist whitelist = new Whitelist();
|
||||
private Whitelist internalWhitelist = new Whitelist();
|
||||
private Whitelist externalWhitelist = new Whitelist();
|
||||
private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
|
||||
|
||||
public Whitelist getWhitelist() {
|
||||
return whitelist;
|
||||
public Whitelist getInternalWhitelist() {
|
||||
return internalWhitelist;
|
||||
}
|
||||
|
||||
public Whitelist getExternalWhitelist() {
|
||||
return externalWhitelist;
|
||||
}
|
||||
|
||||
public CordovaPreferences getPreferences() {
|
||||
@@ -77,6 +82,11 @@ public class ConfigXmlParser {
|
||||
boolean insideFeature = false;
|
||||
ArrayList<String> urlMap = null;
|
||||
|
||||
// Add implicitly allowed URLs
|
||||
internalWhitelist.addWhiteListEntry("file:///*", false);
|
||||
internalWhitelist.addWhiteListEntry("content:///*", false);
|
||||
internalWhitelist.addWhiteListEntry("data:*", false);
|
||||
|
||||
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
||||
if (eventType == XmlResourceParser.START_TAG) {
|
||||
String strNode = xml.getName();
|
||||
@@ -104,8 +114,21 @@ public class ConfigXmlParser {
|
||||
else if (strNode.equals("access")) {
|
||||
String origin = xml.getAttributeValue(null, "origin");
|
||||
String subdomains = xml.getAttributeValue(null, "subdomains");
|
||||
boolean external = (xml.getAttributeValue(null, "launch-external") != null);
|
||||
if (origin != null) {
|
||||
whitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||
if (external) {
|
||||
externalWhitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||
} else {
|
||||
if ("*".equals(origin)) {
|
||||
// Special-case * origin to mean http and https when used for internal
|
||||
// whitelist. This prevents external urls like sms: and geo: from being
|
||||
// handled internally.
|
||||
internalWhitelist.addWhiteListEntry("http://*/*", false);
|
||||
internalWhitelist.addWhiteListEntry("https://*/*", false);
|
||||
} else {
|
||||
internalWhitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strNode.equals("preference")) {
|
||||
|
||||
@@ -49,6 +49,7 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.ValueCallback;
|
||||
@@ -72,6 +73,7 @@ import android.widget.LinearLayout;
|
||||
* @Override
|
||||
* public void onCreate(Bundle savedInstanceState) {
|
||||
* super.onCreate(savedInstanceState);
|
||||
* super.init();
|
||||
* // Load your application
|
||||
* loadUrl(launchUrl);
|
||||
* }
|
||||
@@ -130,7 +132,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
|
||||
// Read from config.xml:
|
||||
protected CordovaPreferences preferences;
|
||||
protected Whitelist whitelist;
|
||||
protected Whitelist internalWhitelist;
|
||||
protected Whitelist externalWhitelist;
|
||||
protected String launchUrl;
|
||||
protected ArrayList<PluginEntry> pluginEntries;
|
||||
|
||||
@@ -199,14 +202,33 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
|
||||
LOG.d(TAG, "CordovaActivity.onCreate()");
|
||||
|
||||
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
|
||||
loadConfig();
|
||||
if(!preferences.getBoolean("ShowTitle", false))
|
||||
{
|
||||
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
}
|
||||
|
||||
if(preferences.getBoolean("SetFullscreen", false))
|
||||
{
|
||||
Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
} else if (preferences.getBoolean("Fullscreen", false)) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
} else {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if(savedInstanceState != null)
|
||||
{
|
||||
initCallbackClass = savedInstanceState.getString("callbackClass");
|
||||
}
|
||||
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -216,7 +238,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
preferences = parser.getPreferences();
|
||||
preferences.setPreferencesBundle(getIntent().getExtras());
|
||||
preferences.copyIntoIntentExtras(this);
|
||||
whitelist = parser.getWhitelist();
|
||||
internalWhitelist = parser.getInternalWhitelist();
|
||||
externalWhitelist = parser.getExternalWhitelist();
|
||||
launchUrl = parser.getLaunchUrl();
|
||||
pluginEntries = parser.getPluginEntries();
|
||||
Config.parser = parser;
|
||||
@@ -225,7 +248,9 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void createViews() {
|
||||
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
|
||||
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
|
||||
|
||||
LOG.d(TAG, "CordovaActivity.createViews()");
|
||||
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
int width = display.getWidth();
|
||||
int height = display.getHeight();
|
||||
@@ -243,13 +268,19 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
|
||||
// Add web view but make it invisible while loading URL
|
||||
appView.setVisibility(View.INVISIBLE);
|
||||
|
||||
// need to remove appView from any existing parent before invoking root.addView(appView)
|
||||
ViewParent parent = appView.getParent();
|
||||
if ((parent != null) && (parent != root)) {
|
||||
LOG.d(TAG, "removing appView from existing parent");
|
||||
ViewGroup parentGroup = (ViewGroup) parent;
|
||||
parentGroup.removeView(appView);
|
||||
}
|
||||
root.addView((View) appView);
|
||||
setContentView(root);
|
||||
|
||||
// TODO: Setting this on the appView causes it to show when <html style="opacity:0">.
|
||||
int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
|
||||
root.setBackgroundColor(backgroundColor);
|
||||
appView.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,29 +333,11 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
|
||||
LOG.d(TAG, "CordovaActivity.init()");
|
||||
|
||||
if(!preferences.getBoolean("ShowTitle", false))
|
||||
{
|
||||
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
}
|
||||
|
||||
if(preferences.getBoolean("SetFullscreen", false))
|
||||
{
|
||||
Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
} else if (preferences.getBoolean("Fullscreen", false)) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
} else {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
}
|
||||
|
||||
appView = webView != null ? webView : makeWebView();
|
||||
if (appView.pluginManager == null) {
|
||||
appView.init(this, webViewClient != null ? webViewClient : makeWebViewClient(appView),
|
||||
webChromeClient != null ? webChromeClient : makeChromeClient(appView),
|
||||
pluginEntries, whitelist, preferences);
|
||||
pluginEntries, internalWhitelist, externalWhitelist, preferences);
|
||||
}
|
||||
|
||||
// TODO: Have the views set this themselves.
|
||||
@@ -789,7 +802,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
|
||||
// If errorUrl specified, then load it
|
||||
final String errorUrl = preferences.getString("errorUrl", null);
|
||||
if ((errorUrl != null) && (errorUrl.startsWith("file://") || whitelist.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
|
||||
if ((errorUrl != null) && (errorUrl.startsWith("file://") || internalWhitelist.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
|
||||
|
||||
// Load URL on UI thread
|
||||
me.runOnUiThread(new Runnable() {
|
||||
@@ -849,7 +862,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
*/
|
||||
@Deprecated // Use whitelist object directly.
|
||||
public boolean isUrlWhiteListed(String url) {
|
||||
return whitelist.isUrlWhiteListed(url);
|
||||
return internalWhitelist.isUrlWhiteListed(url);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -65,6 +65,9 @@ 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;
|
||||
|
||||
@@ -123,7 +126,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
dlg.show();
|
||||
lastHandledDialog = dlg.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,7 +175,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
dlg.show();
|
||||
lastHandledDialog = dlg.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -216,7 +219,7 @@ public class CordovaChromeClient extends WebChromeClient {
|
||||
res.cancel();
|
||||
}
|
||||
});
|
||||
dlg.show();
|
||||
lastHandledDialog = dlg.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -328,4 +331,11 @@ public class CordovaChromeClient extends WebChromeClient {
|
||||
public ValueCallback<Uri> getValueCallback() {
|
||||
return this.mUploadMessage;
|
||||
}
|
||||
|
||||
public void destroyLastDialog(){
|
||||
if(lastHandledDialog != null){
|
||||
lastHandledDialog.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,18 +48,11 @@ class CordovaUriHelper {
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
||||
boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// The WebView should support http and https when going on the Internet
|
||||
if(url.startsWith("http:") || url.startsWith("https:"))
|
||||
{
|
||||
// We only need to whitelist sites on the Internet!
|
||||
if(appView.getWhitelist().isUrlWhiteListed(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Give plugins the chance to handle the url
|
||||
else if (this.appView.pluginManager.onOverrideUrlLoading(url)) {
|
||||
|
||||
if (this.appView.pluginManager.onOverrideUrlLoading(url)) {
|
||||
// Do nothing other than what the plugins wanted.
|
||||
// If any returned true, then the request was handled.
|
||||
return true;
|
||||
}
|
||||
else if(url.startsWith("file://") | url.startsWith("data:"))
|
||||
{
|
||||
@@ -67,7 +60,11 @@ class CordovaUriHelper {
|
||||
//DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!
|
||||
return url.contains("app_webview");
|
||||
}
|
||||
else
|
||||
else if (appView.getWhitelist().isUrlWhiteListed(url)) {
|
||||
// Allow internal navigation
|
||||
return false;
|
||||
}
|
||||
else if (appView.getExternalWhitelist().isUrlWhiteListed(url))
|
||||
{
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
@@ -78,11 +75,12 @@ class CordovaUriHelper {
|
||||
intent.setSelector(null);
|
||||
}
|
||||
this.cordova.getActivity().startActivity(intent);
|
||||
return true;
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error loading url " + url, e);
|
||||
}
|
||||
}
|
||||
//Default behaviour should be to load the default intent, let's see what happens!
|
||||
// Intercept the request and do nothing with it -- block it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.6.0-dev";
|
||||
public static final String CORDOVA_VERSION = "3.7.0-dev";
|
||||
|
||||
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
|
||||
|
||||
@@ -88,7 +88,9 @@ public class CordovaWebView extends WebView {
|
||||
private WebChromeClient.CustomViewCallback mCustomViewCallback;
|
||||
|
||||
private CordovaResourceApi resourceApi;
|
||||
private Whitelist whitelist;
|
||||
private Whitelist internalWhitelist;
|
||||
private Whitelist externalWhitelist;
|
||||
|
||||
// The URL passed to loadUrl(), not necessarily the URL of the current page.
|
||||
String loadedUrl;
|
||||
private CordovaPreferences preferences;
|
||||
@@ -135,14 +137,16 @@ public class CordovaWebView extends WebView {
|
||||
|
||||
// Use two-phase init so that the control will work with XML layouts.
|
||||
public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient,
|
||||
List<PluginEntry> pluginEntries, Whitelist whitelist, CordovaPreferences preferences) {
|
||||
List<PluginEntry> pluginEntries, Whitelist internalWhitelist, Whitelist externalWhitelist,
|
||||
CordovaPreferences preferences) {
|
||||
if (this.cordova != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.cordova = cordova;
|
||||
this.viewClient = webViewClient;
|
||||
this.chromeClient = webChromeClient;
|
||||
this.whitelist = whitelist;
|
||||
this.internalWhitelist = internalWhitelist;
|
||||
this.externalWhitelist = externalWhitelist;
|
||||
this.preferences = preferences;
|
||||
super.setWebChromeClient(webChromeClient);
|
||||
super.setWebViewClient(webViewClient);
|
||||
@@ -165,7 +169,7 @@ public class CordovaWebView extends WebView {
|
||||
if (!Config.isInitialized()) {
|
||||
Config.init(cdv.getActivity());
|
||||
}
|
||||
init(cdv, makeWebViewClient(cdv), makeWebChromeClient(cdv), Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
|
||||
init(cdv, makeWebViewClient(cdv), makeWebChromeClient(cdv), Config.getPluginEntries(), Config.getWhitelist(), Config.getExternalWhitelist(), Config.getPreferences());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,9 +323,13 @@ public class CordovaWebView extends WebView {
|
||||
|
||||
|
||||
public Whitelist getWhitelist() {
|
||||
return this.whitelist;
|
||||
return this.internalWhitelist;
|
||||
}
|
||||
|
||||
|
||||
public Whitelist getExternalWhitelist() {
|
||||
return this.externalWhitelist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
@@ -427,7 +435,7 @@ public class CordovaWebView extends WebView {
|
||||
if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
|
||||
LOG.d(TAG, ">>> loadUrlNow()");
|
||||
}
|
||||
if (url.startsWith("file://") || url.startsWith("javascript:") || whitelist.isUrlWhiteListed(url)) {
|
||||
if (url.startsWith("file://") || url.startsWith("javascript:") || internalWhitelist.isUrlWhiteListed(url)) {
|
||||
super.loadUrl(url);
|
||||
}
|
||||
}
|
||||
@@ -560,7 +568,7 @@ public class CordovaWebView extends WebView {
|
||||
if (!openExternal) {
|
||||
|
||||
// Make sure url is in whitelist
|
||||
if (url.startsWith("file://") || whitelist.isUrlWhiteListed(url)) {
|
||||
if (url.startsWith("file://") || internalWhitelist.isUrlWhiteListed(url)) {
|
||||
// TODO: What about params?
|
||||
// Load new URL
|
||||
this.loadUrl(url);
|
||||
@@ -780,6 +788,9 @@ 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) {
|
||||
|
||||
@@ -98,10 +98,6 @@ public class Whitelist {
|
||||
|
||||
public Whitelist() {
|
||||
this.whiteList = new ArrayList<URLPattern>();
|
||||
// Add implicitly allowed URLs
|
||||
addWhiteListEntry("file:///*", false);
|
||||
addWhiteListEntry("content:///*", false);
|
||||
addWhiteListEntry("data:*", false);
|
||||
}
|
||||
|
||||
/* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
|
||||
|
||||
55
package.json
55
package.json
@@ -1,28 +1,29 @@
|
||||
{
|
||||
"name": "cordova-android",
|
||||
"version": "3.4.0",
|
||||
"description": "cordova-android release",
|
||||
"main": "bin/create",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
|
||||
},
|
||||
"keywords": [
|
||||
"android",
|
||||
"cordova",
|
||||
"apache"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "jasmine-node --color spec"
|
||||
},
|
||||
"author": "Apache Software Foundation",
|
||||
"license": "Apache version 2.0",
|
||||
"dependencies": {
|
||||
"q": "^0.9.0",
|
||||
"shelljs": "^0.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jasmine-node": "~1",
|
||||
"promise-matchers": "~0"
|
||||
}
|
||||
}
|
||||
"name": "cordova-android",
|
||||
"version": "3.7.0-dev",
|
||||
"description": "cordova-android release",
|
||||
"main": "bin/create",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
|
||||
},
|
||||
"keywords": [
|
||||
"android",
|
||||
"cordova",
|
||||
"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\""
|
||||
},
|
||||
"author": "Apache Software Foundation",
|
||||
"license": "Apache version 2.0",
|
||||
"dependencies": {
|
||||
"q": "^0.9.0",
|
||||
"shelljs": "^0.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jasmine-node": "~1",
|
||||
"promise-matchers": "~0"
|
||||
}
|
||||
}
|
||||
@@ -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 "CordovaTest" icon on device
|
||||
0. Run tests by clicking on "CordovaNativeTests" app icon on the device
|
||||
|
||||
To run from Eclipse:
|
||||
|
||||
|
||||
@@ -14,6 +14,25 @@
|
||||
"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.$
|
||||
under the License.
|
||||
-->
|
||||
This is an error page.
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=320, user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>Expected Error</title>
|
||||
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
|
||||
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
|
||||
</head>
|
||||
<body onload="init();" id="stage" class="theme">
|
||||
<h1>Expected Error</h1>
|
||||
<div id="info">
|
||||
<h4>Cordova: <span id="cordova"> </span></h4>
|
||||
<h4>Deviceready: <span id="deviceready"> </span></h4>
|
||||
</div>
|
||||
<div id="info">
|
||||
This is an expected error page because the initial href doesn't exist.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
</head>
|
||||
<body onload="init();" id="stage" class="theme">
|
||||
<h1>Cordova Android Tests</h1>
|
||||
<h1>Cordova Android Native Tests</h1>
|
||||
<div id="info">
|
||||
<h4>Cordova: <span id="cordova"> </span></h4>
|
||||
<h4>Deviceready: <span id="deviceready"> </span></h4>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<h4>Deviceready: <span id="deviceready"> </span></h4>
|
||||
</div>
|
||||
<div id="info">
|
||||
<h4>The menu items should be:</h4>
|
||||
<h4>The options menu items should be:</h4>
|
||||
<li>Item1<br>
|
||||
<li>Item2<br>
|
||||
<li>Item3<br>
|
||||
|
||||
@@ -18,5 +18,5 @@
|
||||
under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">CordovaTests</string>
|
||||
<string name="app_name">CordovaNativeTests</string>
|
||||
</resources>
|
||||
|
||||
@@ -26,10 +26,15 @@
|
||||
Apache Cordova Team
|
||||
</author>
|
||||
<access origin="*.apache.org" />
|
||||
<access origin="http://*.google.com/*" />
|
||||
<access origin="https://*.google.com/*" />
|
||||
<access origin="https://*.googleapis.com/*" />
|
||||
<access origin="https://*.gstatic.com/*" />
|
||||
<content src="index.html" />
|
||||
<preference name="loglevel" value="DEBUG" />
|
||||
<preference name="useBrowserHistory" value="true" />
|
||||
<preference name="exit-on-suspend" value="false" />
|
||||
<preference name="showTitle" value="true" />
|
||||
<feature name="Activity">
|
||||
<param name="android-package" value="org.apache.cordova.test.ActivityPlugin" />
|
||||
</feature>
|
||||
|
||||
@@ -52,7 +52,7 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
|
||||
|
||||
cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
|
||||
cordovaWebView.init(this, new CordovaWebViewClient(this, cordovaWebView), new CordovaChromeClient(this, cordovaWebView),
|
||||
Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
|
||||
Config.getPluginEntries(), Config.getWhitelist(), Config.getExternalWhitelist(), Config.getPreferences());
|
||||
|
||||
cordovaWebView.loadUrl("file:///android_asset/www/index.html");
|
||||
|
||||
@@ -105,4 +105,4 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
|
||||
cordovaWebView.handleDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package org.apache.cordova.test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -21,7 +21,7 @@ package org.apache.cordova.test;
|
||||
import android.os.Bundle;
|
||||
import org.apache.cordova.*;
|
||||
|
||||
public class basicauth extends DroidGap {
|
||||
public class basicauth extends CordovaActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -31,11 +31,13 @@ public class basicauth extends DroidGap {
|
||||
AuthenticationToken token = new AuthenticationToken();
|
||||
token.setUserName("test");
|
||||
token.setPassword("test");
|
||||
super.setAuthenticationToken(token, "browserspy.dk:80", "BrowserSpy.dk - HTTP Password Test");
|
||||
// classic webview includes port in hostname, Chromium webview does not. Handle both here.
|
||||
// BTW, the realm is optional.
|
||||
setAuthenticationToken(token, "browserspy.dk:80", "BrowserSpy.dk - HTTP Password Test");
|
||||
setAuthenticationToken(token, "browserspy.dk", "BrowserSpy.dk - HTTP Password Test");
|
||||
|
||||
// Add web site to whitelist
|
||||
Config.init();
|
||||
Config.addWhiteListEntry("http://browserspy.dk*", true);
|
||||
Config.getWhitelist().addWhiteListEntry("http://browserspy.dk/*", true);
|
||||
|
||||
// Load test
|
||||
super.loadUrl("file:///android_asset/www/basicauth/index.html");
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package org.apache.cordova.test.junit;
|
||||
|
||||
import org.apache.cordova.CordovaWebView;
|
||||
@@ -56,6 +75,7 @@ public class IntentUriOverrideTest extends ActivityInstrumentationTestCase2<Sabo
|
||||
runTestOnUiThread(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
sleep();
|
||||
boolean isBadUrl = testView.getUrl().equals(BAD_URL);
|
||||
assertFalse(isBadUrl);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@ import android.view.ContextMenu.ContextMenuInfo;
|
||||
import org.apache.cordova.*;
|
||||
import org.apache.cordova.LOG;
|
||||
|
||||
public class menus extends DroidGap {
|
||||
public class menus extends CordovaActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// need the title to be shown (config.xml) for the options menu to be visible
|
||||
super.init();
|
||||
super.registerForContextMenu(super.appView);
|
||||
super.loadUrl("file:///android_asset/www/menus/index.html");
|
||||
|
||||
Reference in New Issue
Block a user