Update to new android cordova build

Signed-off-by: Chris Cromer <chris@cromer.cl>
This commit is contained in:
Chris Cromer 2019-04-09 20:33:36 -04:00
parent 408bf02b89
commit 179caec389
414 changed files with 2292 additions and 69850 deletions

View File

@ -36,6 +36,4 @@
<allow-intent href="itms-apps:*" /> <allow-intent href="itms-apps:*" />
</platform> </platform>
<plugin name="cordova-plugin-splashscreen" spec="^5.0.2" /> <plugin name="cordova-plugin-splashscreen" spec="^5.0.2" />
<engine name="browser" spec="^5.0.4" />
<engine name="android" spec="^7.1.4" />
</widget> </widget>

View File

@ -1 +1,2 @@
bin/templates/project/assets/www/cordova.js bin/templates/project/assets/www/cordova.js
test/app

View File

@ -1,6 +1,5 @@
<!-- <!--
Please make sure the checklist boxes are all checked before submitting the PR. The checklist Please make sure the checklist boxes are all checked before submitting the PR. The checklist is intended as a quick reference, for complete details please see our Contributor Guidelines:
is intended as a quick reference, for complete details please see our Contributor Guidelines:
http://cordova.apache.org/contribute/contribute_guidelines.html http://cordova.apache.org/contribute/contribute_guidelines.html
@ -10,13 +9,27 @@ Thanks!
### Platforms affected ### Platforms affected
### What does this PR do?
### Motivation and Context
<!-- Why is this change required? What problem does it solve? -->
<!-- If it fixes an open issue, please link to the issue here. -->
### What testing has been done on this change?
### Description
<!-- Describe your changes in detail -->
### Testing
<!-- Please describe in detail how you tested your changes. -->
### Checklist ### Checklist
- [ ] [Reported an issue](http://cordova.apache.org/contribute/issues.html) in the JIRA database
- [ ] Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected. - [ ] I've run the tests to see all new and existing tests pass
- [ ] Added automated test coverage as appropriate for this change. - [ ] I added automated test coverage as appropriate for this change
- [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`)
- [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/))
- [ ] I've updated the documentation if necessary

View File

@ -2,27 +2,36 @@ language: android
sudo: false sudo: false
jdk: jdk:
- oraclejdk8 - oraclejdk8
env:
global:
- ANDROID_TOOLS=${ANDROID_HOME}/tools
before_install:
- nvm install 6
# ensure at least gradle 3.3 is in place.
- wget http://services.gradle.org/distributions/gradle-3.3-bin.zip
- unzip gradle-3.3-bin.zip
- export GRADLE_HOME=$PWD/gradle-3.3
- export PATH=${GRADLE_HOME}/bin:${ANDROID_HOME}:${ANDROID_HOME}/emulator:${ANDROID_TOOLS}:${ANDROID_TOOLS}/bin:${ANDROID_HOME}/platform-tools:$PATH
- node --version
- gradle --version
- echo y | android --silent update sdk --no-ui --all --filter platform-tools,tools,build-tools-26.0.2,android-26,android-25,extra-google-m2repository,extra-android-m2repository
android: android:
components: components:
- tools - build-tools-28.0.3
env:
global:
# Keep gradle from crapping all over the log
- TERM=dumb
matrix:
- nodejs_version=6
- nodejs_version=8
- nodejs_version=10
install: install:
# Install a sdkmanager version that supports the --licenses switch and
# accept any Android SDK licenses. The output redirection prevents us from
# hitting the travis log size limit of 4MB which would fail the build.
- yes | sdkmanager tools > /dev/null
- yes | sdkmanager --licenses > /dev/null
- nvm install $nodejs_version
- npm install - npm install
- npm install -g codecov - npm install -g codecov
script: script:
- gradle --version
- node --version
- npm --version
- npm test - npm test
- npm run cover - npm run cover
after_script: after_script:
- codecov - codecov

View File

@ -30,7 +30,6 @@ For instructions on this, start with the
[contribution overview](http://cordova.apache.org/contribute/). [contribution overview](http://cordova.apache.org/contribute/).
The details are explained there, but the important items are: The details are explained there, but the important items are:
- Sign and submit an Apache ICLA (Contributor License Agreement).
- Have a Jira issue open that corresponds to your contribution. - Have a Jira issue open that corresponds to your contribution.
- Run the tests so your patch doesn't break existing functionality. - Run the tests so your patch doesn't break existing functionality.

View File

@ -31,9 +31,6 @@ at the core, applications written with web technology: HTML, CSS and JavaScript.
[Apache Cordova](https://cordova.apache.org) is a project of The Apache Software Foundation (ASF). [Apache Cordova](https://cordova.apache.org) is a project of The Apache Software Foundation (ASF).
:warning: Report issues on the [Apache Cordova issue tracker](https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20%28Open%2C%20%22In%20Progress%22%2C%20Reopened%29%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20%22Android%22%20ORDER%20BY%20priority%20DESC%2C%20summary%20ASC%2C%20updatedDate%20DESC)
## Requires ## Requires
- Java JDK 1.8 or greater - Java JDK 1.8 or greater

View File

@ -20,37 +20,58 @@
--> -->
## Release Notes for Cordova (Android) ## ## Release Notes for Cordova (Android) ##
### 7.1.4 (Nov 22, 2018) ### 8.0.0 (Feb 13, 2019)
* [GH-669](https://github.com/apache/cordova-android/pull/669) Added Missing License Headers
* Update android-versions to `1.4.0`, with added support for Android Pie ([#573](https://github.com/apache/cordova-android/pull/573)) * [GH-655](https://github.com/apache/cordova-android/pull/655) Use custom Gradle properties to read minSdkVersion value from `config.xml`
* Output current package name if package name can't be validated ([#567](https://github.com/apache/cordova-android/pull/567)) * [GH-656](https://github.com/apache/cordova-android/pull/656) Quick fix to support **Android**_SDK_ROOT
* Resolve issue with plugin `target-dir="*app*"` subdirs ([#572](https://github.com/apache/cordova-android/pull/572)) * [GH-632](https://github.com/apache/cordova-android/pull/632) Ignore more Gradle build artifacts in **Android** project
* [GH-642](https://github.com/apache/cordova-android/pull/642) **Android** tools 3.3 & **Gradle** 4.10.3 update
### 7.1.3 (Nov 19, 2018) * [GH-654](https://github.com/apache/cordova-android/pull/654) Quick updates to top-level `project.properties`
* [GH-635](https://github.com/apache/cordova-android/pull/635) Ignore **Android** Studio `.idea` files in project
* [GH-624](https://github.com/apache/cordova-android/pull/624) Add missing log to Java version check
* [GH-630](https://github.com/apache/cordova-android/pull/630) Update `emulator.js` to fix issue [GH-608](https://github.com/apache/cordova-android/pull/608)
* [GH-626](https://github.com/apache/cordova-android/pull/626) Added `package-lock.json` to `.gitignore`
* [GH-620](https://github.com/apache/cordova-android/pull/620) Fix requirements error messages for JDK 8
* [GH-619](https://github.com/apache/cordova-android/pull/619) javac error message fixes in requirements check
* [GH-612](https://github.com/apache/cordova-android/pull/612) Android Platform Release Preparation (Cordova 9)
* [GH-607](https://github.com/apache/cordova-android/pull/607) Copy `node_modules` if the directory exists
* [GH-582](https://github.com/apache/cordova-android/pull/582) Improve Test `README`
* [GH-589](https://github.com/apache/cordova-android/pull/589) Rewrite install dir resolution for legacy plugins
* [GH-572](https://github.com/apache/cordova-android/pull/572) Resolve issue with plugin `target-dir="app*"` subdirs
* [GH-567](https://github.com/apache/cordova-android/pull/567) Output current package name if package name can't be validated
* [GH-507](https://github.com/apache/cordova-android/pull/507) Gradle Updates
* [GH-559](https://github.com/apache/cordova-android/pull/559) Eslint ignore version file
* [GH-550](https://github.com/apache/cordova-android/pull/550) Fix for old plugins with non-Java sources
* [GH-558](https://github.com/apache/cordova-android/pull/558) Update `cordova.js` from `cordova-js@4.2.3`
* [GH-553](https://github.com/apache/cordova-android/pull/553) Check for `build-extras.gradle` in the app-parent directory
* [GH-551](https://github.com/apache/cordova-android/pull/551) Add missing cast for `cdvMinSdkVersion`
* [GH-539](https://github.com/apache/cordova-android/pull/539) Fix destination path fallback
* [GH-544](https://github.com/apache/cordova-android/pull/544) Remove obsolete check for JellyBean
* [GH-465](https://github.com/apache/cordova-android/pull/465) Removes Gradle property in-line command arguments for `gradle.properties`
* [GH-523](https://github.com/apache/cordova-android/pull/523) Always put the Google repo above jcenter
* [GH-486](https://github.com/apache/cordova-android/pull/486) Change deprecated "compile" to "implementation"
* [GH-495](https://github.com/apache/cordova-android/pull/495) Incorrect default sdk version issue fix * [GH-495](https://github.com/apache/cordova-android/pull/495) Incorrect default sdk version issue fix
* [GH-496](https://github.com/apache/cordova-android/pull/496) update comments in `build.gradle` * [GH-493](https://github.com/apache/cordova-android/pull/493) Remove bundled dependencies
* [GH-539](https://github.com/apache/cordova-android/pull/539) Fix dest overwrite, in case of of plugin `source-file` element with `target-dir` that does not need remapping * [GH-490](https://github.com/apache/cordova-android/pull/490) Fixes build & run related bugs from builder refactor
* [GH-540](https://github.com/apache/cordova-android/issues/540) support plugin `source-file` element with any app `target-dir` value * [GH-464](https://github.com/apache/cordova-android/pull/464) Unit tests for **Android**_sdk and **Android**Project
* [GH-547](https://github.com/apache/cordova-android/issues/547) Compatibility of old plugins with non-Java `source-file` entries (individual files) * [GH-448](https://github.com/apache/cordova-android/pull/448) [CB-13685](https://issues.apache.org/jira/browse/CB-13685) Adaptive Icon Support
* [GH-551](https://github.com/apache/cordova-android/pull/551) add missing cast for cdvMinSdkVersion to `build.gradle` * [GH-487](https://github.com/apache/cordova-android/pull/487) Do not attempt an activity intent AND a url load into the webview, return from the internal webview load.
* [GH-552](https://github.com/apache/cordova-android/issues/552) check for `build-extras.gradle` in the parent app directory * [GH-461](https://github.com/apache/cordova-android/pull/461) Remove old builders code
* [GH-463](https://github.com/apache/cordova-android/pull/463) Emulator: Add unit tests and remove Q
### 7.1.2 (Nov 08, 2018) * [GH-462](https://github.com/apache/cordova-android/pull/462) Device: Add unit tests and remove Q
* [CB-14127](https://issues.apache.org/jira/browse/CB-14127): Always put the Google repo above jcenter * [GH-457](https://github.com/apache/cordova-android/pull/457) Emulator: handle "device still connecting" error
* [CB-14165](https://issues.apache.org/jira/browse/CB-14165): Emulator: handle "device still connecting" error (#457) * [GH-445](https://github.com/apache/cordova-android/pull/445) Run and retryPromise improvements and tests
* [CB-14125](https://issues.apache.org/jira/browse/CB-14125): Increase old plugin compatibility * [GH-453](https://github.com/apache/cordova-android/pull/453) Lint JS files w/out extension too
* [CB-13830](https://issues.apache.org/jira/browse/CB-13830): Add handlers for plugins that use non-Java source files, such as Camera * [GH-452](https://github.com/apache/cordova-android/pull/452) Emit log event instead of logging directly
* [CB-14038](https://issues.apache.org/jira/browse/CB-14038): fix false positive detecting project type * [GH-449](https://github.com/apache/cordova-android/pull/449) Increase old plugin compatibility
* [GH-442](https://github.com/apache/cordova-android/pull/442) Fixes and cleanup for Java tests and CI
### 7.1.1 (Jul 11, 2018) * [GH-446](https://github.com/apache/cordova-android/pull/446) [CB-14101](https://issues.apache.org/jira/browse/CB-14101) Fix Java version check for Java >= 9
* Fix unsafe property access in run.js (#445) * [CB-14127](https://issues.apache.org/jira/browse/CB-14127) Move google maven repo ahead of jcenter
* Emit log event instead of logging directly (#452) * [CB-14038](https://issues.apache.org/jira/browse/CB-14038) Fix false positive detecting project type
* [CB-14101](https://issues.apache.org/jira/browse/CB-14101) Fix Java version check for Java >= 9 (#446) * [CB-14008](https://issues.apache.org/jira/browse/CB-14008) Updating Gradle Libraries to work with **Android** Studio 3.1.0
* [CB-14127](https://issues.apache.org/jira/browse/CB-14127) (android) Move google maven repo ahead of jcenter * [CB-13975](https://issues.apache.org/jira/browse/CB-13975) Fix to fire pause event when cdvStartInBackground=true
* [CB-13923](https://issues.apache.org/jira/browse/CB-13923) (android) fix -1 length for compressed files * [CB-13830](https://issues.apache.org/jira/browse/CB-13830) Add handlers for plugins that use non-Java source files, such as Camera
* [CB-14145](https://issues.apache.org/jira/browse/CB-14145) use cordova-common@2.2.5 and update other dependencies to resolve `npm audit` warnings * [CB-13923](https://issues.apache.org/jira/browse/CB-13923) Fix -1 length for compressed files
* [CB-9366](https://issues.apache.org/jira/browse/CB-9366) log error.stack in cordova.js
### 7.1.0 (Feb 20, 2018) ### 7.1.0 (Feb 20, 2018)
* [CB-13879](https://issues.apache.org/jira/browse/CB-13879) updated gradle tools dependency to 3.0.1 for project template * [CB-13879](https://issues.apache.org/jira/browse/CB-13879) updated gradle tools dependency to 3.0.1 for project template

View File

@ -1 +1 @@
7.1.4 8.0.0

View File

@ -1,38 +1,36 @@
image:
- Previous Visual Studio 2015
environment: environment:
ANDROID_HOME: "C:\\android" ANDROID_HOME: "C:\\android"
matrix:
- nodejs_version: "4"
- nodejs_version: "6"
- nodejs_version: "8"
init: # If the gradle daemon is used, the build hangs after generating the wrapper
- mkdir "%ANDROID_HOME% GRADLE_OPTS: -Dorg.gradle.daemon=false
- cd "%ANDROID_HOME%"
- appveyor DownloadFile "https://dl.google.com/android/repository/tools_r25.2.3-windows.zip" # URL for SDK Tools, Revision 26.1.1 (September 2017)
- 7z x "tools_r25.2.3-windows.zip" > nul SDK_TOOLS_URL: https://dl.google.com/android/repository/sdk-tools-windows-4333796.zip
- cd "C:\projects\cordova-android"
matrix:
- nodejs_version: 6
- nodejs_version: 8
- nodejs_version: 10
install: install:
- choco install gradle -version 3.4.1 # Install Android SDK Tools
- gradle -version - mkdir "%ANDROID_HOME%"
- echo y | "%ANDROID_HOME%\tools\android.bat" --silent update sdk --no-ui --all --filter platform-tools,tools,build-tools-26.0.2,android-26,android-25,extra-google-m2repository,extra-android-m2repository - appveyor DownloadFile "%SDK_TOOLS_URL%" -FileName "%TMP%/sdk-tools.zip"
# on windows we need to accept sublicenses for the new tooling, wee. 30 is an arbitrary number, - 7z x "%TMP%/sdk-tools.zip" -o"%ANDROID_HOME%" > nul
# but should be the maximum number of licenses we explicitly need to type "Y ENTER" for. - set PATH=%PATH%;"%ANDROID_HOME%\tools\bin"
# also, the sdkmanager in all its glory leaks a bit of output to stderr, and powershell
# and appveyor interpret that as errors, and blows up. so, when piping in our "Y ENTER" - yes 2> nul | sdkmanager --licenses > nul
# responses, we invoke cmd so we can redirect stderr to stdout, and tell it to --update itself. - sdkmanager "build-tools;28.0.3"
- ps: for($i=0;$i -lt 30;$i++) { $response += "y`n"}; $response | cmd /c 'C:\android\tools\bin\sdkmanager.bat 2>&1' --update
- choco install gradle --version 3.4.1
- ps: Install-Product node $env:nodejs_version - ps: Install-Product node $env:nodejs_version
- npm install - npm install
# below is a workaround on using gradle installed via choco on appveyor
- set path=C:\ProgramData\chocolatey\lib\gradle\tools\gradle-3.4.1\bin;%path%
build: off build: off
test_script: test_script:
- gradle --version
- node --version - node --version
- npm --version - npm --version
- npm test - npm test

View File

@ -21,9 +21,7 @@
var android_sdk = require('./templates/cordova/lib/android_sdk'); var android_sdk = require('./templates/cordova/lib/android_sdk');
android_sdk.print_newest_available_sdk_target().done(null, function(err) { android_sdk.print_newest_available_sdk_target().done(null, function (err) {
console.error(err); console.error(err);
process.exit(2); process.exit(2);
}); });

View File

@ -22,9 +22,10 @@
var check_reqs = require('./templates/cordova/lib/check_reqs'); var check_reqs = require('./templates/cordova/lib/check_reqs');
check_reqs.run().done( check_reqs.run().done(
function success() { function success () {
console.log('Looks like your environment fully supports cordova-android development!'); console.log('Looks like your environment fully supports cordova-android development!');
}, function fail(err) { },
function fail (err) {
console.log(err); console.log(err);
process.exit(2); process.exit(2);
} }

View File

@ -23,12 +23,12 @@ var ConfigParser = require('cordova-common').ConfigParser;
var Api = require('./templates/cordova/Api'); var Api = require('./templates/cordova/Api');
var argv = require('nopt')({ var argv = require('nopt')({
'help' : Boolean, 'help': Boolean,
'cli' : Boolean, 'cli': Boolean,
'shared' : Boolean, 'shared': Boolean,
'link' : Boolean, 'link': Boolean,
'activity-name' : [String, undefined] 'activity-name': [String, undefined]
}, { 'd' : '--verbose' }); }, { 'd': '--verbose' });
if (argv.help || argv.argv.remain.length === 0) { if (argv.help || argv.argv.remain.length === 0) {
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]'); console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');

View File

@ -141,9 +141,9 @@ function writeProjectProperties (projectPath, target_api) {
} }
// This makes no sense, what if you're building with a different build system? // This makes no sense, what if you're building with a different build system?
function prepBuildFiles (projectPath, builder) { function prepBuildFiles (projectPath) {
var buildModule = require(path.resolve(projectPath, 'cordova/lib/builders/builders')); var buildModule = require(path.resolve(projectPath, 'cordova/lib/builders/builders'));
buildModule.getBuilder(builder).prepBuildFiles(); buildModule.getBuilder().prepBuildFiles();
} }
function copyBuildRules (projectPath, isLegacy) { function copyBuildRules (projectPath, isLegacy) {
@ -168,7 +168,10 @@ function copyScripts (projectPath) {
shell.rm('-rf', destScriptsDir); shell.rm('-rf', destScriptsDir);
// Copy in the new ones. // Copy in the new ones.
shell.cp('-r', srcScriptsDir, projectPath); shell.cp('-r', srcScriptsDir, projectPath);
shell.cp('-r', path.join(ROOT, 'node_modules'), destScriptsDir);
let nodeModulesDir = path.join(ROOT, 'node_modules');
if (fs.existsSync(nodeModulesDir)) shell.cp('-r', nodeModulesDir, destScriptsDir);
shell.cp(path.join(bin, 'check_reqs*'), destScriptsDir); shell.cp(path.join(bin, 'check_reqs*'), destScriptsDir);
shell.cp(path.join(bin, 'android_sdk_version*'), destScriptsDir); shell.cp(path.join(bin, 'android_sdk_version*'), destScriptsDir);
var check_reqs = path.join(destScriptsDir, 'check_reqs'); var check_reqs = path.join(destScriptsDir, 'check_reqs');
@ -329,7 +332,7 @@ exports.create = function (project_path, config, options, events) {
}); });
// Link it to local android install. // Link it to local android install.
exports.writeProjectProperties(project_path, target_api); exports.writeProjectProperties(project_path, target_api);
exports.prepBuildFiles(project_path, 'studio'); exports.prepBuildFiles(project_path);
events.emit('log', generateDoneMessage('create', options.link)); events.emit('log', generateDoneMessage('create', options.link));
}).thenResolve(project_path); }).thenResolve(project_path);
}; };

View File

@ -21,7 +21,6 @@ var path = require('path');
var Q = require('q'); var Q = require('q');
var AndroidProject = require('./lib/AndroidProject'); var AndroidProject = require('./lib/AndroidProject');
var AndroidStudio = require('./lib/AndroidStudio');
var PluginManager = require('cordova-common').PluginManager; var PluginManager = require('cordova-common').PluginManager;
var CordovaLogger = require('cordova-common').CordovaLogger; var CordovaLogger = require('cordova-common').CordovaLogger;
@ -56,41 +55,27 @@ function setupEvents (externalEventEmitter) {
function Api (platform, platformRootDir, events) { function Api (platform, platformRootDir, events) {
this.platform = PLATFORM; this.platform = PLATFORM;
this.root = path.resolve(__dirname, '..'); this.root = path.resolve(__dirname, '..');
this.builder = 'gradle';
setupEvents(events); setupEvents(events);
var self = this; const appMain = path.join(this.root, 'app', 'src', 'main');
const appRes = path.join(appMain, 'res');
this.locations = { this.locations = {
root: self.root, root: this.root,
www: path.join(self.root, 'assets/www'), www: path.join(appMain, 'assets', 'www'),
res: path.join(self.root, 'res'), res: appRes,
platformWww: path.join(self.root, 'platform_www'), platformWww: path.join(this.root, 'platform_www'),
configXml: path.join(self.root, 'res/xml/config.xml'), configXml: path.join(appRes, 'xml', 'config.xml'),
defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'), defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'),
strings: path.join(self.root, 'res/values/strings.xml'), strings: path.join(appRes, 'values', 'strings.xml'),
manifest: path.join(self.root, 'AndroidManifest.xml'), manifest: path.join(appMain, 'AndroidManifest.xml'),
build: path.join(self.root, 'build'), build: path.join(this.root, 'build'),
javaSrc: path.join(self.root, 'src'), javaSrc: path.join(appMain, 'java'),
// NOTE: Due to platformApi spec we need to return relative paths here // NOTE: Due to platformApi spec we need to return relative paths here
cordovaJs: 'bin/templates/project/assets/www/cordova.js', cordovaJs: 'bin/templates/project/assets/www/cordova.js',
cordovaJsSrc: 'cordova-js-src' cordovaJsSrc: 'cordova-js-src'
}; };
// XXX Override some locations for Android Studio projects
if (AndroidStudio.isAndroidStudioProject(self.root) === true) {
selfEvents.emit('log', 'Android Studio project detected');
this.builder = 'studio';
this.android_studio = true;
this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml');
this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml');
this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml');
// We could have Java Source, we could have other languages
this.locations.javaSrc = path.join(self.root, 'app/src/main/java/');
this.locations.www = path.join(self.root, 'app/src/main/assets/www');
this.locations.res = path.join(self.root, 'app/src/main/res');
}
} }
/** /**
@ -223,33 +208,13 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
installOptions.variables.PACKAGE_NAME = project.getPackageName(); installOptions.variables.PACKAGE_NAME = project.getPackageName();
} }
if (this.android_studio === true) {
installOptions.android_studio = true;
}
return Q().then(function () { return Q().then(function () {
// CB-11964: Do a clean when installing the plugin code to get around
// the Gradle bug introduced by the Android Gradle Plugin Version 2.2
// TODO: Delete when the next version of Android Gradle plugin comes out
// Since clean doesn't just clean the build, it also wipes out www, we need
// to pass additional options.
// Do some basic argument parsing
var opts = {};
// Skip cleaning prepared files when not invoking via cordova CLI.
opts.noPrepare = true;
if (!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
return self.clean(opts);
}
}).then(function () {
return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions); return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
}).then(function () { }).then(function () {
if (plugin.getFrameworks(this.platform).length === 0) return; if (plugin.getFrameworks(this.platform).length === 0) return;
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>'); selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
// This should pick the correct builder, not just get gradle // This should pick the correct builder, not just get gradle
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles(); require('./lib/builders/builders').getBuilder().prepBuildFiles();
}.bind(this)) }.bind(this))
// CB-11022 Return truthy value to prevent running prepare after // CB-11022 Return truthy value to prevent running prepare after
.thenResolve(true); .thenResolve(true);
@ -271,9 +236,8 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
Api.prototype.removePlugin = function (plugin, uninstallOptions) { Api.prototype.removePlugin = function (plugin, uninstallOptions) {
var project = AndroidProject.getProjectFile(this.root); var project = AndroidProject.getProjectFile(this.root);
if (uninstallOptions && uninstallOptions.usePlatformWww === true && this.android_studio === true) { if (uninstallOptions && uninstallOptions.usePlatformWww === true) {
uninstallOptions.usePlatformWww = false; uninstallOptions.usePlatformWww = false;
uninstallOptions.android_studio = true;
} }
return PluginManager.get(this.platform, this.locations, project) return PluginManager.get(this.platform, this.locations, project)
@ -282,7 +246,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
if (plugin.getFrameworks(this.platform).length === 0) return; if (plugin.getFrameworks(this.platform).length === 0) return;
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>'); selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles(); require('./lib/builders/builders').getBuilder().prepBuildFiles();
}.bind(this)) }.bind(this))
// CB-11022 Return truthy value to prevent running prepare after // CB-11022 Return truthy value to prevent running prepare after
.thenResolve(true); .thenResolve(true);
@ -335,9 +299,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
*/ */
Api.prototype.build = function (buildOptions) { Api.prototype.build = function (buildOptions) {
var self = this; var self = this;
if (this.android_studio) {
buildOptions.studio = true;
}
return require('./lib/check_reqs').run().then(function () { return require('./lib/check_reqs').run().then(function () {
return require('./lib/build').run.call(self, buildOptions); return require('./lib/build').run.call(self, buildOptions);
}).then(function (buildResults) { }).then(function (buildResults) {
@ -381,13 +343,10 @@ Api.prototype.run = function (runOptions) {
*/ */
Api.prototype.clean = function (cleanOptions) { Api.prototype.clean = function (cleanOptions) {
var self = this; var self = this;
if (this.android_studio) {
// This will lint, checking for null won't // This will lint, checking for null won't
if (typeof cleanOptions === 'undefined') { if (typeof cleanOptions === 'undefined') {
cleanOptions = {}; cleanOptions = {};
} }
cleanOptions.studio = true;
}
return require('./lib/check_reqs').run().then(function () { return require('./lib/check_reqs').run().then(function () {
return require('./lib/build').runClean.call(self, cleanOptions); return require('./lib/build').runClean.call(self, cleanOptions);

View File

@ -25,18 +25,19 @@ var nopt = require('nopt');
var path = require('path'); var path = require('path');
// Support basic help commands // Support basic help commands
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(args[2]) >= 0) {
require('./lib/build').help(); require('./lib/build').help();
}
// Do some basic argument parsing // Do some basic argument parsing
var buildOpts = nopt({ var buildOpts = nopt({
'verbose' : Boolean, 'verbose': Boolean,
'silent' : Boolean, 'silent': Boolean,
'debug' : Boolean, 'debug': Boolean,
'release' : Boolean, 'release': Boolean,
'nobuild': Boolean, 'nobuild': Boolean,
'buildConfig' : path 'buildConfig': path
}, { 'd' : '--verbose' }); }, { 'd': '--verbose' });
// Make buildOptions compatible with PlatformApi build method spec // Make buildOptions compatible with PlatformApi build method spec
buildOpts.argv = buildOpts.argv.original; buildOpts.argv = buildOpts.argv.original;
@ -44,7 +45,7 @@ buildOpts.argv = buildOpts.argv.original;
require('./loggingHelper').adjustLoggerLevel(buildOpts); require('./loggingHelper').adjustLoggerLevel(buildOpts);
new Api().build(buildOpts) new Api().build(buildOpts)
.catch(function(err) { .catch(function (err) {
console.error(err.stack); console.error(err.stack);
process.exit(2); process.exit(2);
}); });

View File

@ -24,7 +24,7 @@ var path = require('path');
var nopt = require('nopt'); var nopt = require('nopt');
// Support basic help commands // Support basic help commands
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) { if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1])); console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
console.log('Cleans the project directory.'); console.log('Cleans the project directory.');
process.exit(0); process.exit(0);
@ -32,9 +32,9 @@ if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >=
// Do some basic argument parsing // Do some basic argument parsing
var opts = nopt({ var opts = nopt({
'verbose' : Boolean, 'verbose': Boolean,
'silent' : Boolean 'silent': Boolean
}, { 'd' : '--verbose' }); }, { 'd': '--verbose' });
// Make buildOptions compatible with PlatformApi clean method spec // Make buildOptions compatible with PlatformApi clean method spec
opts.argv = opts.argv.original; opts.argv = opts.argv.original;
@ -45,7 +45,7 @@ opts.noPrepare = true;
require('./loggingHelper').adjustLoggerLevel(opts); require('./loggingHelper').adjustLoggerLevel(opts);
new Api().clean(opts) new Api().clean(opts)
.catch(function(err) { .catch(function (err) {
console.error(err.stack); console.error(err.stack);
process.exit(2); process.exit(2);
}); });

View File

@ -44,7 +44,7 @@ function isEmulator (line) {
* devices/emulators * devices/emulators
*/ */
Adb.devices = function (opts) { Adb.devices = function (opts) {
return spawn('adb', ['devices'], {cwd: os.tmpdir()}).then(function (output) { return spawn('adb', ['devices'], { cwd: os.tmpdir() }).then(function (output) {
return output.split('\n').filter(function (line) { return output.split('\n').filter(function (line) {
// Filter out either real devices or emulators, depending on options // Filter out either real devices or emulators, depending on options
return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line); return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
@ -58,7 +58,7 @@ Adb.install = function (target, packagePath, opts) {
events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...'); events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
var args = ['-s', target, 'install']; var args = ['-s', target, 'install'];
if (opts && opts.replace) args.push('-r'); if (opts && opts.replace) args.push('-r');
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()}).then(function (output) { return spawn('adb', args.concat(packagePath), { cwd: os.tmpdir() }).then(function (output) {
// 'adb install' seems to always returns no error, even if installation fails // 'adb install' seems to always returns no error, even if installation fails
// so we catching output to detect installation failure // so we catching output to detect installation failure
if (output.match(/Failure/)) { if (output.match(/Failure/)) {
@ -77,14 +77,14 @@ Adb.install = function (target, packagePath, opts) {
Adb.uninstall = function (target, packageId) { Adb.uninstall = function (target, packageId) {
events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...'); events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...');
return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()}); return spawn('adb', ['-s', target, 'uninstall', packageId], { cwd: os.tmpdir() });
}; };
Adb.shell = function (target, shellCommand) { Adb.shell = function (target, shellCommand) {
events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...'); events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
var args = ['-s', target, 'shell']; var args = ['-s', target, 'shell'];
shellCommand = shellCommand.split(/\s+/); shellCommand = shellCommand.split(/\s+/);
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}).catch(function (output) { return spawn('adb', args.concat(shellCommand), { cwd: os.tmpdir() }).catch(function (output) {
return Q.reject(new CordovaError('Failed to execute shell command "' + return Q.reject(new CordovaError('Failed to execute shell command "' +
shellCommand + '"" on device: ' + output)); shellCommand + '"" on device: ' + output));
}); });

View File

@ -51,15 +51,11 @@ AndroidManifest.prototype.setVersionCode = function (versionCode) {
}; };
AndroidManifest.prototype.getPackageId = function () { AndroidManifest.prototype.getPackageId = function () {
/* jshint -W069 */
return this.doc.getroot().attrib['package']; return this.doc.getroot().attrib['package'];
/* jshint +W069 */
}; };
AndroidManifest.prototype.setPackageId = function (pkgId) { AndroidManifest.prototype.setPackageId = function (pkgId) {
/* jshint -W069 */
this.doc.getroot().attrib['package'] = pkgId; this.doc.getroot().attrib['package'] = pkgId;
/* jshint +W069 */
return this; return this;
}; };
@ -150,7 +146,7 @@ AndroidManifest.prototype.setDebuggable = function (value) {
* manifest will be written to file it has been read from. * manifest will be written to file it has been read from.
*/ */
AndroidManifest.prototype.write = function (destPath) { AndroidManifest.prototype.write = function (destPath) {
fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8'); fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8');
}; };
module.exports = AndroidManifest; module.exports = AndroidManifest;

View File

@ -21,7 +21,6 @@ var fs = require('fs');
var path = require('path'); var path = require('path');
var properties_parser = require('properties-parser'); var properties_parser = require('properties-parser');
var AndroidManifest = require('./AndroidManifest'); var AndroidManifest = require('./AndroidManifest');
var AndroidStudio = require('./AndroidStudio');
var pluginHandlers = require('./pluginHandlers'); var pluginHandlers = require('./pluginHandlers');
var projectFileCache = {}; var projectFileCache = {};
@ -62,10 +61,7 @@ function AndroidProject (projectDir) {
this._dirty = false; this._dirty = false;
this.projectDir = projectDir; this.projectDir = projectDir;
this.platformWww = path.join(this.projectDir, 'platform_www'); this.platformWww = path.join(this.projectDir, 'platform_www');
this.www = path.join(this.projectDir, 'assets/www');
if (AndroidStudio.isAndroidStudioProject(projectDir) === true) {
this.www = path.join(this.projectDir, 'app/src/main/assets/www'); this.www = path.join(this.projectDir, 'app/src/main/assets/www');
}
} }
AndroidProject.getProjectFile = function (projectDir) { AndroidProject.getProjectFile = function (projectDir) {
@ -92,10 +88,7 @@ AndroidProject.purgeCache = function (projectDir) {
* @return {String} The name of the package * @return {String} The name of the package
*/ */
AndroidProject.prototype.getPackageName = function () { AndroidProject.prototype.getPackageName = function () {
var manifestPath = path.join(this.projectDir, 'AndroidManifest.xml'); var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
if (AndroidStudio.isAndroidStudioProject(this.projectDir) === true) {
manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
}
return new AndroidManifest(manifestPath).getPackageId(); return new AndroidManifest(manifestPath).getPackageId();
}; };

View File

@ -1,11 +0,0 @@
/*
* This is a simple routine that checks if project is an Android Studio Project
*
* @param {String} root Root folder of the project
*/
/* jshint esnext: false */
module.exports.isAndroidStudioProject = function isAndroidStudioProject (root) {
return true;
};

View File

@ -17,7 +17,6 @@
under the License. under the License.
*/ */
var Q = require('q');
var superspawn = require('cordova-common').superspawn; var superspawn = require('cordova-common').superspawn;
var suffix_number_regex = /(\d+)$/; var suffix_number_regex = /(\d+)$/;
@ -95,7 +94,7 @@ module.exports.list_targets = function () {
} else throw err; } else throw err;
}).then(function (targets) { }).then(function (targets) {
if (targets.length === 0) { if (targets.length === 0) {
return Q.reject(new Error('No android targets (SDKs) installed!')); return Promise.reject(new Error('No android targets (SDKs) installed!'));
} }
return targets; return targets;
}); });

View File

@ -31,11 +31,10 @@ var events = require('cordova-common').events;
var spawn = require('cordova-common').superspawn.spawn; var spawn = require('cordova-common').superspawn.spawn;
var CordovaError = require('cordova-common').CordovaError; var CordovaError = require('cordova-common').CordovaError;
module.exports.parseBuildOptions = parseOpts;
function parseOpts (options, resolvedTarget, projectRoot) { function parseOpts (options, resolvedTarget, projectRoot) {
options = options || {}; options = options || {};
options.argv = nopt({ options.argv = nopt({
gradle: Boolean,
studio: Boolean,
prepenv: Boolean, prepenv: Boolean,
versionCode: String, versionCode: String,
minSdkVersion: String, minSdkVersion: String,
@ -50,26 +49,13 @@ function parseOpts (options, resolvedTarget, projectRoot) {
// Android Studio Build method is the default // Android Studio Build method is the default
var ret = { var ret = {
buildType: options.release ? 'release' : 'debug', buildType: options.release ? 'release' : 'debug',
buildMethod: process.env.ANDROID_BUILD || 'studio',
prepEnv: options.argv.prepenv, prepEnv: options.argv.prepenv,
arch: resolvedTarget && resolvedTarget.arch, arch: resolvedTarget && resolvedTarget.arch,
extraArgs: [] extraArgs: []
}; };
if (options.argv.gradle || options.argv.studio) {
ret.buildMethod = options.argv.studio ? 'studio' : 'gradle';
}
// This comes from cordova/run
if (options.studio) ret.buildMethod = 'studio';
if (options.gradle) ret.buildMethod = 'gradle';
if (options.nobuild) ret.buildMethod = 'none';
if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); } if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); } if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
if (options.argv.gradleArg) { if (options.argv.gradleArg) {
ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg); ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
} }
@ -129,7 +115,8 @@ function parseOpts (options, resolvedTarget, projectRoot) {
*/ */
module.exports.runClean = function (options) { module.exports.runClean = function (options) {
var opts = parseOpts(options, null, this.root); var opts = parseOpts(options, null, this.root);
var builder = builders.getBuilder(opts.buildMethod); var builder = builders.getBuilder();
return builder.prepEnv(opts).then(function () { return builder.prepEnv(opts).then(function () {
return builder.clean(opts); return builder.clean(opts);
}); });
@ -149,8 +136,8 @@ module.exports.runClean = function (options) {
*/ */
module.exports.run = function (options, optResolvedTarget) { module.exports.run = function (options, optResolvedTarget) {
var opts = parseOpts(options, optResolvedTarget, this.root); var opts = parseOpts(options, optResolvedTarget, this.root);
console.log(opts.buildMethod); var builder = builders.getBuilder();
var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts).then(function () { return builder.prepEnv(opts).then(function () {
if (opts.prepEnv) { if (opts.prepEnv) {
events.emit('verbose', 'Build file successfully prepared.'); events.emit('verbose', 'Build file successfully prepared.');
@ -161,8 +148,7 @@ module.exports.run = function (options, optResolvedTarget) {
events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t')); events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
return { return {
apkPaths: apkPaths, apkPaths: apkPaths,
buildType: opts.buildType, buildType: opts.buildType
buildMethod: opts.buildMethod
}; };
}); });
}); });
@ -276,12 +262,10 @@ module.exports.help = function () {
console.log('Flags:'); console.log('Flags:');
console.log(' \'--debug\': will build project in debug mode (default)'); console.log(' \'--debug\': will build project in debug mode (default)');
console.log(' \'--release\': will build project for release'); console.log(' \'--release\': will build project for release');
console.log(' \'--ant\': will build project with ant');
console.log(' \'--gradle\': will build project with gradle (default)');
console.log(' \'--nobuild\': will skip build process (useful when using run command)'); console.log(' \'--nobuild\': will skip build process (useful when using run command)');
console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary'); console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary');
console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.'); console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs.');
console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.'); console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs.');
console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true'); console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
console.log(''); console.log('');
console.log('Signed APK flags (overwrites debug/release-signing.proprties) :'); console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');

View File

@ -1,124 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* eslint no-self-assign: 0 */
/* eslint no-unused-vars: 0 */
var Q = require('q');
var fs = require('fs');
var path = require('path');
var shell = require('shelljs');
var events = require('cordova-common').events;
function GenericBuilder (projectDir) {
this.root = projectDir || path.resolve(__dirname, '../../..');
this.binDirs = {
studio: path.join(this.root, 'app', 'build', 'outputs', 'apk'),
gradle: path.join(this.root, 'build', 'outputs', 'apk')
};
}
GenericBuilder.prototype.prepEnv = function () {
return Q();
};
GenericBuilder.prototype.build = function () {
events.emit('log', 'Skipping build...');
return Q(null);
};
GenericBuilder.prototype.clean = function () {
return Q();
};
GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
var self = this;
return Object.keys(this.binDirs).reduce(function (result, builderName) {
var binDir = self.binDirs[builderName];
return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
}, []).sort(apkSorter);
};
module.exports = GenericBuilder;
function apkSorter (fileA, fileB) {
// De-prioritize arch specific builds
var archSpecificRE = /-x86|-arm/;
if (archSpecificRE.exec(fileA)) {
return 1;
} else if (archSpecificRE.exec(fileB)) {
return -1;
}
// De-prioritize unsigned builds
var unsignedRE = /-unsigned/;
if (unsignedRE.exec(fileA)) {
return 1;
} else if (unsignedRE.exec(fileB)) {
return -1;
}
var timeDiff = fs.statSync(fileB).mtime - fs.statSync(fileA).mtime;
return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
}
function findOutputApksHelper (dir, build_type, arch) {
var shellSilent = shell.config.silent;
shell.config.silent = true;
// list directory recursively
var ret = shell.ls('-R', dir).map(function (file) {
// ls does not include base directory
return path.join(dir, file);
}).filter(function (file) {
// find all APKs
return file.match(/\.apk?$/i);
}).filter(function (candidate) {
var apkName = path.basename(candidate);
// Need to choose between release and debug .apk.
if (build_type === 'debug') {
return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
}
if (build_type === 'release') {
return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
}
return true;
}).sort(apkSorter);
shellSilent = shellSilent;
if (ret.length === 0) {
return ret;
}
// Assume arch-specific build if newest apk has -x86 or -arm.
var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
// And show only arch-specific ones (or non-arch-specific)
ret = ret.filter(function (p) {
/* jshint -W018 */
return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
/* jshint +W018 */
});
if (archSpecific && ret.length > 1 && arch) {
ret = ret.filter(function (p) {
return path.basename(p).indexOf('-' + arch) !== -1;
});
}
return ret;
}

View File

@ -1,331 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var Q = require('q');
var fs = require('fs');
var util = require('util');
var path = require('path');
var shell = require('shelljs');
var superspawn = require('cordova-common').superspawn;
var CordovaError = require('cordova-common').CordovaError;
var events = require('cordova-common').events;
var check_reqs = require('../check_reqs');
var GenericBuilder = require('./GenericBuilder');
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
var SIGNING_PROPERTIES = '-signing.properties';
var TEMPLATE =
'# This file is automatically generated.\n' +
'# Do not modify this file -- ' + MARKER + '\n';
function GradleBuilder (projectRoot) {
GenericBuilder.call(this, projectRoot);
this.binDirs = { gradle: this.binDirs.gradle };
}
util.inherits(GradleBuilder, GenericBuilder);
GradleBuilder.prototype.getArgs = function (cmd, opts) {
if (cmd === 'release') {
cmd = 'cdvBuildRelease';
} else if (cmd === 'debug') {
cmd = 'cdvBuildDebug';
}
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
if (opts.arch) {
args.push('-PcdvBuildArch=' + opts.arch);
}
// 10 seconds -> 6 seconds
args.push('-Dorg.gradle.daemon=true');
// to allow dex in process
args.push('-Dorg.gradle.jvmargs=-Xmx2048m');
// allow NDK to be used - required by Gradle 1.5 plugin
args.push('-Pandroid.useDeprecatedNdk=true');
args.push.apply(args, opts.extraArgs);
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
// args.push('-Dorg.gradle.parallel=true');
return args;
};
/*
* This returns a promise
*/
GradleBuilder.prototype.runGradleWrapper = function (gradle_cmd, gradle_file) {
var gradlePath = path.join(this.root, 'gradlew');
gradle_file = path.join(this.root, (gradle_file || 'wrapper.gradle'));
if (fs.existsSync(gradlePath)) {
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
} else {
return superspawn.spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', gradle_file], { stdio: 'pipe' })
.progress(function (stdio) {
suppressJavaOptionsInfo(stdio);
});
}
};
/*
* We need to kill this in a fire.
*/
GradleBuilder.prototype.readProjectProperties = function () {
function findAllUniq (data, r) {
var s = {};
var m;
while ((m = r.exec(data))) {
s[m[1]] = 1;
}
return Object.keys(s);
}
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
return {
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
};
};
GradleBuilder.prototype.extractRealProjectNameFromManifest = function () {
var manifestPath = path.join(this.root, 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m) {
throw new CordovaError('Could not find package name in ' + manifestPath);
}
var packageName = m[1];
var lastDotIndex = packageName.lastIndexOf('.');
return packageName.substring(lastDotIndex + 1);
};
// Makes the project buildable, minus the gradle wrapper.
GradleBuilder.prototype.prepBuildFiles = function () {
// Update the version of build.gradle in each dependent library.
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
var propertiesObj = this.readProjectProperties();
var subProjects = propertiesObj.libs;
// Check and copy the gradle file into the subproject.
// Called by the loop below this function def.
var checkAndCopy = function (subProject, root) {
var subProjectGradle = path.join(root, subProject, 'build.gradle');
// This is the future-proof way of checking if a file exists
// This must be synchronous to satisfy a Travis test
try {
fs.accessSync(subProjectGradle, fs.F_OK);
} catch (e) {
shell.cp('-f', pluginBuildGradle, subProjectGradle);
}
};
// Some dependencies on Android don't use gradle, or don't have default
// gradle files. This copies a dummy gradle file into them
for (var i = 0; i < subProjects.length; ++i) {
if (subProjects[i] !== 'CordovaLib' && subProjects[i] !== 'app') {
checkAndCopy(subProjects[i], this.root);
}
}
var name = this.extractRealProjectNameFromManifest();
// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
var settingsGradlePaths = subProjects.map(function (p) {
var realDir = p.replace(/[/\\]/g, ':');
var libName = realDir.replace(name + '-', '');
var str = 'include ":' + libName + '"\n';
if (realDir.indexOf(name + '-') !== -1) { str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n'; }
return str;
});
// Write the settings.gradle file.
fs.writeFileSync(path.join(this.root, 'settings.gradle'),
'// GENERATED FILE - DO NOT EDIT\n' +
'include ":"\n' + settingsGradlePaths.join(''));
// Update dependencies within build.gradle.
var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
var depsList = '';
var root = this.root;
// Cordova Plugins can be written as library modules that would use Cordova as a
// dependency. Because we need to make sure that Cordova is compiled only once for
// dexing, we make sure to exclude CordovaLib from these modules
var insertExclude = function (p) {
var gradlePath = path.join(root, p, 'build.gradle');
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
if (projectGradleFile.indexOf('CordovaLib') !== -1) {
depsList += '{\n exclude module:("CordovaLib")\n }\n';
} else {
depsList += '\n';
}
};
subProjects.forEach(function (p) {
events.emit('log', 'Subproject Path: ' + p);
var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
depsList += ' implementation(project(path: "' + libName + '"))';
insertExclude(p);
});
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
var SYSTEM_LIBRARY_MAPPINGS = [
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
];
propertiesObj.systemLibs.forEach(function (p) {
var mavenRef;
// It's already in gradle form if it has two ':'s
if (/:.*:/.exec(p)) {
mavenRef = p;
} else {
for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
var pair = SYSTEM_LIBRARY_MAPPINGS[i];
if (pair[0].exec(p)) {
mavenRef = p.replace(pair[0], pair[1]);
break;
}
}
if (!mavenRef) {
throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
}
}
depsList += ' compile "' + mavenRef + '"\n';
});
// This code is dangerous and actually writes gradle declarations directly into the build.gradle
// Try not to mess with this if possible
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
var includeList = '';
propertiesObj.gradleIncludes.forEach(function (includePath) {
includeList += 'apply from: "' + includePath + '"\n';
});
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
fs.writeFileSync(path.join(this.root, 'build.gradle'), buildGradle);
};
GradleBuilder.prototype.prepEnv = function (opts) {
var self = this;
return check_reqs.check_gradle().then(function (gradlePath) {
return self.runGradleWrapper(gradlePath);
}).then(function () {
return self.prepBuildFiles();
}).then(function () {
// We now copy the gradle out of the framework
// This is a dirty patch to get the build working
/*
var wrapperDir = path.join(self.root, 'CordovaLib');
if (process.platform == 'win32') {
shell.rm('-f', path.join(self.root, 'gradlew.bat'));
shell.cp(path.join(wrapperDir, 'gradlew.bat'), self.root);
} else {
shell.rm('-f', path.join(self.root, 'gradlew'));
shell.cp(path.join(wrapperDir, 'gradlew'), self.root);
}
shell.rm('-rf', path.join(self.root, 'gradle', 'wrapper'));
shell.mkdir('-p', path.join(self.root, 'gradle'));
shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(self.root, 'gradle'));
*/
// If the gradle distribution URL is set, make sure it points to version we want.
// 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.
// For some reason, using ^ and $ don't work. This does the job, though.
var distributionUrlRegex = /distributionUrl.*zip/;
/* jshint -W069 */
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-4.1-all.zip';
/* jshint +W069 */
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.chmod('u+w', gradleWrapperPropertiesPath);
shell.sed('-i', distributionUrlRegex, 'distributionUrl=' + distributionUrl, gradleWrapperPropertiesPath);
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
var propertiesFilePath = path.join(self.root, propertiesFile);
if (opts.packageInfo) {
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
} else if (isAutoGenerated(propertiesFilePath)) {
shell.rm('-f', propertiesFilePath);
}
});
};
/*
* Builds the project with gradle.
* Returns a promise.
*/
GradleBuilder.prototype.build = function (opts) {
var wrapper = path.join(this.root, 'gradlew');
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
return superspawn.spawn(wrapper, args, { stdio: 'pipe' })
.progress(function (stdio) {
suppressJavaOptionsInfo(stdio);
}).catch(function (error) {
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
return check_reqs.check_android_target(error).then(function () {
// If due to some odd reason - check_android_target succeeds
// we should still fail here.
return Q.reject(error);
});
}
return Q.reject(error);
});
};
GradleBuilder.prototype.clean = function (opts) {
var builder = this;
var wrapper = path.join(this.root, 'gradlew');
var args = builder.getArgs('clean', opts);
return Q().then(function () {
return superspawn.spawn(wrapper, args, { stdio: 'inherit' });
}).then(function () {
shell.rm('-rf', path.join(builder.root, 'out'));
['debug', 'release'].forEach(function (config) {
var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
if (isAutoGenerated(propertiesFilePath)) {
shell.rm('-f', propertiesFilePath);
}
});
});
};
module.exports = GradleBuilder;
function suppressJavaOptionsInfo (stdio) {
if (stdio.stderr) {
/*
* Workaround for the issue with Java printing some unwanted information to
* stderr instead of stdout.
* This function suppresses 'Picked up _JAVA_OPTIONS' message from being
* printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
* explanation.
*/
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
if (suppressThisLine) {
return;
}
process.stderr.write(stdio.stderr);
} else {
process.stdout.write(stdio.stdout);
}
}
function isAutoGenerated (file) {
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
}

View File

@ -1,303 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var Q = require('q');
var fs = require('fs');
var util = require('util');
var path = require('path');
var shell = require('shelljs');
var spawn = require('cordova-common').superspawn.spawn;
var events = require('cordova-common').events;
var CordovaError = require('cordova-common').CordovaError;
var check_reqs = require('../check_reqs');
var GenericBuilder = require('./GenericBuilder');
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
var SIGNING_PROPERTIES = '-signing.properties';
var TEMPLATE =
'# This file is automatically generated.\n' +
'# Do not modify this file -- ' + MARKER + '\n';
function StudioBuilder (projectRoot) {
GenericBuilder.call(this, projectRoot);
this.binDirs = {gradle: this.binDirs.studio};
}
util.inherits(StudioBuilder, GenericBuilder);
StudioBuilder.prototype.getArgs = function (cmd, opts) {
if (cmd === 'release') {
cmd = 'cdvBuildRelease';
} else if (cmd === 'debug') {
cmd = 'cdvBuildDebug';
}
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
if (opts.arch) {
args.push('-PcdvBuildArch=' + opts.arch);
}
// 10 seconds -> 6 seconds
args.push('-Dorg.gradle.daemon=true');
// to allow dex in process
args.push('-Dorg.gradle.jvmargs=-Xmx2048m');
// allow NDK to be used - required by Gradle 1.5 plugin
// args.push('-Pandroid.useDeprecatedNdk=true');
args.push.apply(args, opts.extraArgs);
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
// args.push('-Dorg.gradle.parallel=true');
return args;
};
/*
* This returns a promise
*/
StudioBuilder.prototype.runGradleWrapper = function (gradle_cmd) {
var gradlePath = path.join(this.root, 'gradlew');
var wrapperGradle = path.join(this.root, 'wrapper.gradle');
if (fs.existsSync(gradlePath)) {
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
} else {
return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
}
};
StudioBuilder.prototype.readProjectProperties = function () {
function findAllUniq (data, r) {
var s = {};
var m;
while ((m = r.exec(data))) {
s[m[1]] = 1;
}
return Object.keys(s);
}
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
return {
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
};
};
StudioBuilder.prototype.extractRealProjectNameFromManifest = function () {
var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m) {
throw new CordovaError('Could not find package name in ' + manifestPath);
}
var packageName = m[1];
var lastDotIndex = packageName.lastIndexOf('.');
return packageName.substring(lastDotIndex + 1);
};
// Makes the project buildable, minus the gradle wrapper.
StudioBuilder.prototype.prepBuildFiles = function () {
// Update the version of build.gradle in each dependent library.
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
var propertiesObj = this.readProjectProperties();
var subProjects = propertiesObj.libs;
// Check and copy the gradle file into the subproject
// Called by the loop before this function def
var checkAndCopy = function (subProject, root) {
var subProjectGradle = path.join(root, subProject, 'build.gradle');
// This is the future-proof way of checking if a file exists
// This must be synchronous to satisfy a Travis test
try {
fs.accessSync(subProjectGradle, fs.F_OK);
} catch (e) {
shell.cp('-f', pluginBuildGradle, subProjectGradle);
}
};
for (var i = 0; i < subProjects.length; ++i) {
if (subProjects[i] !== 'CordovaLib') {
checkAndCopy(subProjects[i], this.root);
}
}
var name = this.extractRealProjectNameFromManifest();
// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
var settingsGradlePaths = subProjects.map(function (p) {
var realDir = p.replace(/[/\\]/g, ':');
var libName = realDir.replace(name + '-', '');
var str = 'include ":' + libName + '"\n';
if (realDir.indexOf(name + '-') !== -1) {
str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n';
}
return str;
});
fs.writeFileSync(path.join(this.root, 'settings.gradle'),
'// GENERATED FILE - DO NOT EDIT\n' +
'include ":"\n' + settingsGradlePaths.join(''));
// Update dependencies within build.gradle.
var buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
var depsList = '';
var root = this.root;
var insertExclude = function (p) {
var gradlePath = path.join(root, p, 'build.gradle');
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
if (projectGradleFile.indexOf('CordovaLib') !== -1) {
depsList += '{\n exclude module:("CordovaLib")\n }\n';
} else {
depsList += '\n';
}
};
subProjects.forEach(function (p) {
events.emit('log', 'Subproject Path: ' + p);
var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
if (libName !== 'app') {
depsList += ' implementation(project(path: ":' + libName + '"))';
insertExclude(p);
}
});
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
var SYSTEM_LIBRARY_MAPPINGS = [
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
];
propertiesObj.systemLibs.forEach(function (p) {
var mavenRef;
// It's already in gradle form if it has two ':'s
if (/:.*:/.exec(p)) {
mavenRef = p;
} else {
for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
var pair = SYSTEM_LIBRARY_MAPPINGS[i];
if (pair[0].exec(p)) {
mavenRef = p.replace(pair[0], pair[1]);
break;
}
}
if (!mavenRef) {
throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
}
}
depsList += ' compile "' + mavenRef + '"\n';
});
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
var includeList = '';
propertiesObj.gradleIncludes.forEach(function (includePath) {
includeList += 'apply from: "../' + includePath + '"\n';
});
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
// This needs to be stored in the app gradle, not the root grade
fs.writeFileSync(path.join(this.root, 'app', 'build.gradle'), buildGradle);
};
StudioBuilder.prototype.prepEnv = function (opts) {
var self = this;
return check_reqs.check_gradle()
.then(function (gradlePath) {
return self.runGradleWrapper(gradlePath);
}).then(function () {
return self.prepBuildFiles();
}).then(function () {
// If the gradle distribution URL is set, make sure it points to version we want.
// 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.
// For some reason, using ^ and $ don't work. This does the job, though.
var distributionUrlRegex = /distributionUrl.*zip/;
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-4.1-all.zip';
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.chmod('u+w', gradleWrapperPropertiesPath);
shell.sed('-i', distributionUrlRegex, 'distributionUrl=' + distributionUrl, gradleWrapperPropertiesPath);
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
var propertiesFilePath = path.join(self.root, propertiesFile);
if (opts.packageInfo) {
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
} else if (isAutoGenerated(propertiesFilePath)) {
shell.rm('-f', propertiesFilePath);
}
});
};
/*
* Builds the project with gradle.
* Returns a promise.
*/
StudioBuilder.prototype.build = function (opts) {
var wrapper = path.join(this.root, 'gradlew');
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
return spawn(wrapper, args, {stdio: 'pipe'})
.progress(function (stdio) {
if (stdio.stderr) {
/*
* Workaround for the issue with Java printing some unwanted information to
* stderr instead of stdout.
* This function suppresses 'Picked up _JAVA_OPTIONS' message from being
* printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
* explanation.
*/
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
if (suppressThisLine) {
return;
}
process.stderr.write(stdio.stderr);
} else {
process.stdout.write(stdio.stdout);
}
}).catch(function (error) {
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
return check_reqs.check_android_target(error).then(function () {
// If due to some odd reason - check_android_target succeeds
// we should still fail here.
return Q.reject(error);
});
}
return Q.reject(error);
});
};
StudioBuilder.prototype.clean = function (opts) {
var builder = this;
var wrapper = path.join(this.root, 'gradlew');
var args = builder.getArgs('clean', opts);
return Q().then(function () {
return spawn(wrapper, args, {stdio: 'inherit'});
})
.then(function () {
shell.rm('-rf', path.join(builder.root, 'out'));
['debug', 'release'].forEach(function (config) {
var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
if (isAutoGenerated(propertiesFilePath)) {
shell.rm('-f', propertiesFilePath);
}
});
});
};
module.exports = StudioBuilder;
function isAutoGenerated (file) {
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
}

View File

@ -17,30 +17,18 @@
under the License. under the License.
*/ */
var CordovaError = require('cordova-common').CordovaError; const CordovaError = require('cordova-common').CordovaError;
var knownBuilders = {
gradle: 'GradleBuilder',
studio: 'StudioBuilder',
none: 'GenericBuilder'
};
/** /**
* Helper method that instantiates and returns a builder for specified build * Helper method that instantiates and returns a builder for specified build type.
* type.
*
* @param {String} builderType Builder name to construct and return. Must
* be one of 'ant', 'gradle' or 'none'
* *
* @return {Builder} A builder instance for specified build type. * @return {Builder} A builder instance for specified build type.
*/ */
module.exports.getBuilder = function (builderType, projectRoot) { module.exports.getBuilder = function () {
if (!knownBuilders[builderType]) { throw new CordovaError('Builder ' + builderType + ' is not supported.'); }
try { try {
var Builder = require('./' + knownBuilders[builderType]); const Builder = require('./ProjectBuilder');
return new Builder(projectRoot); return new Builder();
} catch (err) { } catch (err) {
throw new CordovaError('Failed to instantiate ' + knownBuilders[builderType] + ' builder: ' + err); throw new CordovaError('Failed to instantiate ProjectBuilder builder: ' + err);
} }
}; };

View File

@ -19,8 +19,6 @@
under the License. under the License.
*/ */
/* jshint sub:true */
var shelljs = require('shelljs'); var shelljs = require('shelljs');
var child_process = require('child_process'); var child_process = require('child_process');
var Q = require('q'); var Q = require('q');
@ -205,10 +203,12 @@ module.exports.check_java = function () {
return match && match[1]; return match && match[1];
}, () => { }, () => {
var msg = var msg =
'Failed to run "javac -version", make sure that you have a JDK installed.\n' + 'Failed to run "javac -version", make sure that you have a JDK version 8 installed.\n' +
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n'; 'You can get it from the following location:\n' +
'https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html';
if (process.env['JAVA_HOME']) { if (process.env['JAVA_HOME']) {
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n'; msg += '\n\n';
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'];
} }
throw new CordovaError(msg); throw new CordovaError(msg);
}); });
@ -231,6 +231,14 @@ module.exports.check_android = function () {
// First ensure ANDROID_HOME is set // First ensure ANDROID_HOME is set
// If we have no hints (nothing in PATH), try a few default locations // If we have no hints (nothing in PATH), try a few default locations
if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) { if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) {
if (process.env['ANDROID_SDK_ROOT']) {
// Quick fix to set ANDROID_HOME according to ANDROID_SDK_ROOT
// if ANDROID_HOME is **not** defined and
// ANDROID_SDK_ROOT **is** defined
// according to environment variables as documented in:
// https://developer.android.com/studio/command-line/variables
maybeSetAndroidHome(path.join(process.env['ANDROID_SDK_ROOT']));
}
if (module.exports.isWindows()) { if (module.exports.isWindows()) {
// Android Studio 1.0 installer // Android Studio 1.0 installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk')); maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
@ -355,15 +363,19 @@ module.exports.check_android_target = function (originalError) {
// Returns a promise. // Returns a promise.
module.exports.run = function () { module.exports.run = function () {
return Q.all([this.check_java(), this.check_android()]).then(function (values) { return Q.all([this.check_java(), this.check_android()]).then(function (values) {
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']); console.log('Checking Java JDK and Android SDK versions');
console.log('JAVA_HOME=' + process.env['JAVA_HOME']); console.log('ANDROID_SDK_ROOT=' + process.env['ANDROID_SDK_ROOT'] + ' (recommended setting)');
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME'] + ' (DEPRECATED)');
if (!String(values[0]).startsWith('1.8.')) { if (!String(values[0]).startsWith('1.8.')) {
throw new CordovaError('Requirements check failed for JDK 1.8'); throw new CordovaError(
'Requirements check failed for JDK 8 (\'1.8.*\')! Detected version: ' + values[0] + '\n' +
'Check your ANDROID_SDK_ROOT / JAVA_HOME / PATH environment variables.'
);
} }
if (!values[1]) { if (!values[1]) {
throw new CordovaError('Requirements check failed for Android SDK'); throw new CordovaError('Requirements check failed for Android SDK! Android SDK was not detected.');
} }
}); });
}; };

View File

@ -19,7 +19,6 @@
under the License. under the License.
*/ */
var Q = require('q');
var build = require('./build'); var build = require('./build');
var path = require('path'); var path = require('path');
var Adb = require('./Adb'); var Adb = require('./Adb');
@ -53,13 +52,13 @@ module.exports.list = function (lookHarder) {
module.exports.resolveTarget = function (target) { module.exports.resolveTarget = function (target) {
return this.list(true).then(function (device_list) { return this.list(true).then(function (device_list) {
if (!device_list || !device_list.length) { if (!device_list || !device_list.length) {
return Q.reject(new CordovaError('Failed to deploy to device, no devices found.')); return Promise.reject(new CordovaError('Failed to deploy to device, no devices found.'));
} }
// default device // default device
target = target || device_list[0]; target = target || device_list[0];
if (device_list.indexOf(target) < 0) { if (device_list.indexOf(target) < 0) {
return Q.reject('ERROR: Unable to find target \'' + target + '\'.'); return Promise.reject(new CordovaError('ERROR: Unable to find target \'' + target + '\'.'));
} }
return build.detectArchitecture(target).then(function (arch) { return build.detectArchitecture(target).then(function (arch) {
@ -74,7 +73,7 @@ module.exports.resolveTarget = function (target) {
* Returns a promise. * Returns a promise.
*/ */
module.exports.install = function (target, buildResults) { module.exports.install = function (target, buildResults) {
return Q().then(function () { return Promise.resolve().then(function () {
if (target && typeof target === 'object') { if (target && typeof target === 'object') {
return target; return target;
} }
@ -87,7 +86,7 @@ module.exports.install = function (target, buildResults) {
events.emit('log', 'Using apk: ' + apk_path); events.emit('log', 'Using apk: ' + apk_path);
events.emit('log', 'Package name: ' + pkgName); events.emit('log', 'Package name: ' + pkgName);
return Adb.install(resolvedTarget.target, apk_path, {replace: true}).catch(function (error) { return Adb.install(resolvedTarget.target, apk_path, { replace: true }).catch(function (error) {
// CB-9557 CB-10157 only uninstall and reinstall app if the one that // CB-9557 CB-10157 only uninstall and reinstall app if the one that
// is already installed on device was signed w/different certificate // is already installed on device was signed w/different certificate
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; } if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
@ -98,7 +97,7 @@ module.exports.install = function (target, buildResults) {
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
// or the app doesn't installed at all, so no error catching needed. // or the app doesn't installed at all, so no error catching needed.
return Adb.uninstall(resolvedTarget.target, pkgName).then(function () { return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
return Adb.install(resolvedTarget.target, apk_path, {replace: true}); return Adb.install(resolvedTarget.target, apk_path, { replace: true });
}); });
}).then(function () { }).then(function () {
// unlock screen // unlock screen

View File

@ -19,8 +19,6 @@
under the License. under the License.
*/ */
/* jshint sub:true */
var android_versions = require('android-versions'); var android_versions = require('android-versions');
var retry = require('./retry'); var retry = require('./retry');
var build = require('./build'); var build = require('./build');
@ -34,7 +32,6 @@ var shelljs = require('shelljs');
var android_sdk = require('./android_sdk'); var android_sdk = require('./android_sdk');
var check_reqs = require('./check_reqs'); var check_reqs = require('./check_reqs');
var Q = require('q');
var os = require('os'); var os = require('os');
var fs = require('fs'); var fs = require('fs');
var child_process = require('child_process'); var child_process = require('child_process');
@ -170,15 +167,13 @@ module.exports.list_images_using_android = function () {
} }
*/ */
module.exports.list_images = function () { module.exports.list_images = function () {
return Q.fcall(function () { return Promise.resolve().then(function () {
if (forgivingWhichSync('avdmanager')) { if (forgivingWhichSync('avdmanager')) {
return module.exports.list_images_using_avdmanager(); return module.exports.list_images_using_avdmanager();
} else if (forgivingWhichSync('android')) { } else if (forgivingWhichSync('android')) {
return module.exports.list_images_using_android(); return module.exports.list_images_using_android();
} else { } else {
return Q().then(function () { return Promise.reject(new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?'));
throw new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?');
});
} }
}).then(function (avds) { }).then(function (avds) {
// In case we're missing the Android OS version string from the target description, add it. // In case we're missing the Android OS version string from the target description, add it.
@ -228,13 +223,13 @@ module.exports.best_image = function () {
// Returns a promise. // Returns a promise.
module.exports.list_started = function () { module.exports.list_started = function () {
return Adb.devices({emulators: true}); return Adb.devices({ emulators: true });
}; };
// Returns a promise. // Returns a promise.
// TODO: we should remove this, there's a more robust method under android_sdk.js // TODO: we should remove this, there's a more robust method under android_sdk.js
module.exports.list_targets = function () { module.exports.list_targets = function () {
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()}).then(function (output) { return superspawn.spawn('android', ['list', 'targets'], { cwd: os.tmpdir() }).then(function (output) {
var target_out = output.split('\n'); var target_out = output.split('\n');
var targets = []; var targets = [];
for (var i = target_out.length; i >= 0; i--) { for (var i = target_out.length; i >= 0; i--) {
@ -277,8 +272,8 @@ module.exports.get_available_port = function () {
module.exports.start = function (emulator_ID, boot_timeout) { module.exports.start = function (emulator_ID, boot_timeout) {
var self = this; var self = this;
return Q().then(function () { return Promise.resolve().then(function () {
if (emulator_ID) return Q(emulator_ID); if (emulator_ID) return Promise.resolve(emulator_ID);
return self.best_image().then(function (best) { return self.best_image().then(function (best) {
if (best && best.name) { if (best && best.name) {
@ -287,7 +282,7 @@ module.exports.start = function (emulator_ID, boot_timeout) {
} }
var androidCmd = check_reqs.getAbsoluteAndroidCmd(); var androidCmd = check_reqs.getAbsoluteAndroidCmd();
return Q.reject(new CordovaError('No emulator images (avds) found.\n' + return Promise.reject(new CordovaError('No emulator images (avds) found.\n' +
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' + '1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
'2. Create an AVD by running: ' + androidCmd + ' avd\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')); 'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
@ -308,7 +303,7 @@ module.exports.start = function (emulator_ID, boot_timeout) {
return self.wait_for_emulator(port); return self.wait_for_emulator(port);
}); });
}).then(function (emulatorId) { }).then(function (emulatorId) {
if (!emulatorId) { return Q.reject(new CordovaError('Failed to start emulator')); } if (!emulatorId) { return Promise.reject(new CordovaError('Failed to start emulator')); }
// wait for emulator to boot up // wait for emulator to boot up
process.stdout.write('Waiting for emulator to boot (this may take a while)...'); process.stdout.write('Waiting for emulator to boot (this may take a while)...');
@ -334,7 +329,7 @@ module.exports.start = function (emulator_ID, boot_timeout) {
*/ */
module.exports.wait_for_emulator = function (port) { module.exports.wait_for_emulator = function (port) {
var self = this; var self = this;
return Q().then(function () { return Promise.resolve().then(function () {
var emulator_id = 'emulator-' + port; var emulator_id = 'emulator-' + port;
return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) { return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
if (output.indexOf('1') >= 0) { if (output.indexOf('1') >= 0) {
@ -345,7 +340,8 @@ module.exports.wait_for_emulator = function (port) {
if ((error && error.message && if ((error && error.message &&
(error.message.indexOf('not found') > -1)) || (error.message.indexOf('not found') > -1)) ||
(error.message.indexOf('device offline') > -1) || (error.message.indexOf('device offline') > -1) ||
(error.message.indexOf('device still connecting') > -1)) { (error.message.indexOf('device still connecting') > -1) ||
(error.message.indexOf('device still authorizing') > -1)) {
// emulator not yet started, continue waiting // emulator not yet started, continue waiting
return self.wait_for_emulator(port); return self.wait_for_emulator(port);
} else { } else {
@ -371,10 +367,13 @@ module.exports.wait_for_boot = function (emulator_id, time_remaining) {
} else { } else {
process.stdout.write('.'); process.stdout.write('.');
// Check at regular intervals return new Promise(resolve => {
return Q.delay(time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL).then(function () { const delay = time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL;
var updated_time = time_remaining >= 0 ? Math.max(time_remaining - CHECK_BOOTED_INTERVAL, 0) : time_remaining;
return self.wait_for_boot(emulator_id, updated_time); setTimeout(() => {
const updated_time = time_remaining >= 0 ? Math.max(time_remaining - CHECK_BOOTED_INTERVAL, 0) : time_remaining;
resolve(self.wait_for_boot(emulator_id, updated_time));
}, delay);
}); });
} }
}); });
@ -400,7 +399,7 @@ module.exports.create_image = function (name, target) {
// TODO: This seems like another error case, even though it always happens. // TODO: This seems like another error case, even though it always happens.
console.error('ERROR : Unable to create an avd emulator, no targets found.'); console.error('ERROR : Unable to create an avd emulator, no targets found.');
console.error('Ensure you have targets available by running the "android" command'); console.error('Ensure you have targets available by running the "android" command');
return Q.reject(); return Promise.reject(new CordovaError());
}, function (error) { }, function (error) {
console.error('ERROR : Failed to create emulator image : '); console.error('ERROR : Failed to create emulator image : ');
console.error(error); console.error(error);
@ -411,17 +410,17 @@ module.exports.create_image = function (name, target) {
module.exports.resolveTarget = function (target) { module.exports.resolveTarget = function (target) {
return this.list_started().then(function (emulator_list) { return this.list_started().then(function (emulator_list) {
if (emulator_list.length < 1) { if (emulator_list.length < 1) {
return Q.reject('No running Android emulators found, please start an emulator before deploying your project.'); return Promise.reject(new CordovaError('No running Android emulators found, please start an emulator before deploying your project.'));
} }
// default emulator // default emulator
target = target || emulator_list[0]; target = target || emulator_list[0];
if (emulator_list.indexOf(target) < 0) { if (emulator_list.indexOf(target) < 0) {
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.'); return Promise.reject(new CordovaError('Unable to find target \'' + target + '\'. Failed to deploy to emulator.'));
} }
return build.detectArchitecture(target).then(function (arch) { return build.detectArchitecture(target).then(function (arch) {
return {target: target, arch: arch, isEmulator: true}; return { target: target, arch: arch, isEmulator: true };
}); });
}); });
}; };
@ -436,15 +435,12 @@ module.exports.install = function (givenTarget, buildResults) {
var target; var target;
// We need to find the proper path to the Android Manifest // We need to find the proper path to the Android Manifest
var manifestPath = path.join(__dirname, '..', '..', 'app', 'src', 'main', 'AndroidManifest.xml'); const manifestPath = path.join(__dirname, '..', '..', 'app', 'src', 'main', 'AndroidManifest.xml');
if (buildResults.buildMethod === 'gradle') { const manifest = new AndroidManifest(manifestPath);
manifestPath = path.join(__dirname, '../../AndroidManifest.xml'); const pkgName = manifest.getPackageId();
}
var manifest = new AndroidManifest(manifestPath);
var pkgName = manifest.getPackageId();
// resolve the target emulator // resolve the target emulator
return Q().then(function () { return Promise.resolve().then(function () {
if (givenTarget && typeof givenTarget === 'object') { if (givenTarget && typeof givenTarget === 'object') {
return givenTarget; return givenTarget;
} else { } else {
@ -459,7 +455,7 @@ module.exports.install = function (givenTarget, buildResults) {
}).then(function () { }).then(function () {
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
// or the app doesn't installed at all, so no error catching needed. // or the app doesn't installed at all, so no error catching needed.
return Q.when().then(function () { return Promise.resolve().then(function () {
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch); var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
var execOptions = { var execOptions = {
@ -479,7 +475,7 @@ module.exports.install = function (givenTarget, buildResults) {
events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...'); events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...');
var command = 'adb -s ' + target + ' install -r "' + apk + '"'; var command = 'adb -s ' + target + ' install -r "' + apk + '"';
return Q.promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
child_process.exec(command, opts, function (err, stdout, stderr) { child_process.exec(command, opts, function (err, stdout, stderr) {
if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr)); if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
// adb does not return an error code even if installation fails. Instead it puts a specific // adb does not return an error code even if installation fails. Instead it puts a specific

View File

@ -19,14 +19,14 @@
under the License. under the License.
*/ */
var device = require('./device'), var device = require('./device');
args = process.argv; var args = process.argv;
if(args.length > 2) { if (args.length > 2) {
var install_target; var install_target;
if (args[2].substring(0, 9) == '--target=') { if (args[2].substring(0, 9) === '--target=') {
install_target = args[2].substring(9, args[2].length); install_target = args[2].substring(9, args[2].length);
device.install(install_target).done(null, function(err) { device.install(install_target).catch(function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });
@ -35,7 +35,7 @@ if(args.length > 2) {
process.exit(2); process.exit(2);
} }
} else { } else {
device.install().done(null, function(err) { device.install().catch(function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -19,12 +19,12 @@
under the License. under the License.
*/ */
var emulator = require('./emulator'), var emulator = require('./emulator');
args = process.argv; var args = process.argv;
var install_target; var install_target;
if(args.length > 2) { if (args.length > 2) {
if (args[2].substring(0, 9) == '--target=') { if (args[2].substring(0, 9) === '--target=') {
install_target = args[2].substring(9, args[2].length); install_target = args[2].substring(9, args[2].length);
} else { } else {
console.error('ERROR : argument \'' + args[2] + '\' not recognized.'); console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
@ -32,7 +32,7 @@ if(args.length > 2) {
} }
} }
emulator.install(install_target).done(null, function(err) { emulator.install(install_target).catch(function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -22,12 +22,12 @@
var devices = require('./device'); var devices = require('./device');
// Usage support for when args are given // Usage support for when args are given
require('./check_reqs').check_android().then(function() { require('./check_reqs').check_android().then(function () {
devices.list().done(function(device_list) { devices.list().then(function (device_list) {
device_list && device_list.forEach(function(dev) { device_list && device_list.forEach(function (dev) {
console.log(dev); console.log(dev);
}); });
}, function(err) { }, function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -22,12 +22,12 @@
var emulators = require('./emulator'); var emulators = require('./emulator');
// Usage support for when args are given // Usage support for when args are given
require('./check_reqs').check_android().then(function() { require('./check_reqs').check_android().then(function () {
emulators.list_images().done(function(emulator_list) { emulators.list_images().then(function (emulator_list) {
emulator_list && emulator_list.forEach(function(emu) { emulator_list && emulator_list.forEach(function (emu) {
console.log(emu.name); console.log(emu.name);
}); });
}, function(err) { }, function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -22,12 +22,12 @@
var emulators = require('./emulator'); var emulators = require('./emulator');
// Usage support for when args are given // Usage support for when args are given
require('./check_reqs').check_android().then(function() { require('./check_reqs').check_android().then(function () {
emulators.list_started().done(function(emulator_list) { emulators.list_started().then(function (emulator_list) {
emulator_list && emulator_list.forEach(function(emu) { emulator_list && emulator_list.forEach(function (emu) {
console.log(emu); console.log(emu);
}); });
}, function(err) { }, function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -31,7 +31,7 @@ var ROOT = path.join(__dirname, '..', '..');
*/ */
module.exports.run = function () { module.exports.run = function () {
var d = Q.defer(); var d = Q.defer();
var adb = child_process.spawn('adb', ['logcat'], {cwd: os.tmpdir()}); var adb = child_process.spawn('adb', ['logcat'], { cwd: os.tmpdir() });
adb.stdout.on('data', function (data) { adb.stdout.on('data', function (data) {
var lines = data ? data.toString().split('\n') : []; var lines = data ? data.toString().split('\n') : [];

View File

@ -20,9 +20,7 @@
buildscript { buildscript {
repositories { repositories {
maven { google()
url "https://maven.google.com"
}
jcenter() jcenter()
} }
@ -38,7 +36,7 @@ buildscript {
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
dependencies { dependencies {
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
debugCompile project(path: ":CordovaLib", configuration: "debug") debugCompile project(path: ":CordovaLib", configuration: "debug")
releaseCompile project(path: ":CordovaLib", configuration: "release") releaseCompile project(path: ":CordovaLib", configuration: "release")
} }
@ -46,7 +44,6 @@ dependencies {
android { android {
compileSdkVersion cdvCompileSdkVersion compileSdkVersion cdvCompileSdkVersion
buildToolsVersion cdvBuildToolsVersion buildToolsVersion cdvBuildToolsVersion
publishNonDefault true
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6 sourceCompatibility JavaVersion.VERSION_1_6

View File

@ -14,8 +14,6 @@
* *
*/ */
/* jshint unused: vars */
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var shell = require('shelljs'); var shell = require('shelljs');
@ -28,14 +26,7 @@ var handlers = {
if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id)); if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id)); if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
var dest = path.join(obj.targetDir, path.basename(obj.src)); var dest = getInstallDestination(obj);
// TODO: This code needs to be replaced, since the core plugins need to be re-mapped to a different location in
// a later plugins release. This is for legacy plugins to work with Cordova.
if (options && options.android_studio === true) {
dest = getInstallDestination(obj);
}
if (options && options.force) { if (options && options.force) {
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link)); copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
@ -44,11 +35,7 @@ var handlers = {
} }
}, },
uninstall: function (obj, plugin, project, options) { uninstall: function (obj, plugin, project, options) {
var dest = path.join(obj.targetDir, path.basename(obj.src)); var dest = getInstallDestination(obj);
if (options && options.android_studio === true) {
dest = getInstallDestination(obj);
}
// TODO: Add Koltin extension to uninstall, since they are handled like Java files // TODO: Add Koltin extension to uninstall, since they are handled like Java files
if (obj.src.endsWith('java')) { if (obj.src.endsWith('java')) {
@ -61,33 +48,21 @@ var handlers = {
}, },
'lib-file': { 'lib-file': {
install: function (obj, plugin, project, options) { install: function (obj, plugin, project, options) {
var dest = path.join('libs', path.basename(obj.src)); var dest = path.join('app/libs', path.basename(obj.src));
if (options && options.android_studio === true) {
dest = path.join('app/libs', path.basename(obj.src));
}
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link)); copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
}, },
uninstall: function (obj, plugin, project, options) { uninstall: function (obj, plugin, project, options) {
var dest = path.join('libs', path.basename(obj.src)); var dest = path.join('app/libs', path.basename(obj.src));
if (options && options.android_studio === true) {
dest = path.join('app/libs', path.basename(obj.src));
}
removeFile(project.projectDir, dest); removeFile(project.projectDir, dest);
} }
}, },
'resource-file': { 'resource-file': {
install: function (obj, plugin, project, options) { install: function (obj, plugin, project, options) {
var dest = path.normalize(obj.target); var dest = path.join('app', 'src', 'main', obj.target);
if (options && options.android_studio === true) {
dest = path.join('app/src/main', dest);
}
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link)); copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
}, },
uninstall: function (obj, plugin, project, options) { uninstall: function (obj, plugin, project, options) {
var dest = path.normalize(obj.target); var dest = path.join('app', 'src', 'main', obj.target);
if (options && options.android_studio === true) {
dest = path.join('app/src/main', dest);
}
removeFile(project.projectDir, dest); removeFile(project.projectDir, dest);
} }
}, },
@ -319,27 +294,41 @@ function generateAttributeError (attribute, element, id) {
function getInstallDestination (obj) { function getInstallDestination (obj) {
var APP_MAIN_PREFIX = 'app/src/main'; var APP_MAIN_PREFIX = 'app/src/main';
var PATH_SEPARATOR = '/';
if (obj.targetDir.startsWith('app')) { var PATH_SEP_MATCH = '\\' + PATH_SEPARATOR;
var PATH_SEP_OR_EOL_MATCH = '(\\' + PATH_SEPARATOR + '|$)';
var appReg = new RegExp('^app' + PATH_SEP_OR_EOL_MATCH);
var libsReg = new RegExp('^libs' + PATH_SEP_OR_EOL_MATCH);
var srcReg = new RegExp('^src' + PATH_SEP_OR_EOL_MATCH);
var srcMainReg = new RegExp('^src' + PATH_SEP_MATCH + 'main' + PATH_SEP_OR_EOL_MATCH);
if (appReg.test(obj.targetDir)) {
// If any source file is using the new app directory structure, // If any source file is using the new app directory structure,
// don't penalize it // don't penalize it
return path.join(obj.targetDir, path.basename(obj.src)); return path.join(obj.targetDir, path.basename(obj.src));
} else if (obj.src.endsWith('.java')) { } else {
return path.join(APP_MAIN_PREFIX, 'java', obj.targetDir.substring(4), path.basename(obj.src)); // Plugin using deprecated target directory structure (GH-580)
if (obj.src.endsWith('.java')) {
return path.join(APP_MAIN_PREFIX, 'java', obj.targetDir.replace(srcReg, ''),
path.basename(obj.src));
} else if (obj.src.endsWith('.aidl')) { } else if (obj.src.endsWith('.aidl')) {
return path.join(APP_MAIN_PREFIX, 'aidl', obj.targetDir.substring(4), path.basename(obj.src)); return path.join(APP_MAIN_PREFIX, 'aidl', obj.targetDir.replace(srcReg, ''),
} else if (obj.targetDir.includes('libs')) { path.basename(obj.src));
} else if (libsReg.test(obj.targetDir)) {
if (obj.src.endsWith('.so')) { if (obj.src.endsWith('.so')) {
return path.join(APP_MAIN_PREFIX, 'jniLibs', obj.targetDir.substring(5), path.basename(obj.src)); return path.join(APP_MAIN_PREFIX, 'jniLibs', obj.targetDir.replace(libsReg, ''),
path.basename(obj.src));
} else { } else {
return path.join('app', obj.targetDir, path.basename(obj.src)); return path.join('app', obj.targetDir, path.basename(obj.src));
} }
} else if (obj.targetDir.includes('src/main')) { } else if (srcMainReg.test(obj.targetDir)) {
return path.join('app', obj.targetDir, path.basename(obj.src)); return path.join('app', obj.targetDir, path.basename(obj.src));
} else { }
// For all other source files not using the new app directory structure, // For all other source files not using the new app directory structure,
// add 'app/src/main' to the targetDir // add 'app/src/main' to the targetDir
return path.join(APP_MAIN_PREFIX, obj.targetDir, path.basename(obj.src)); return path.join(APP_MAIN_PREFIX, obj.targetDir, path.basename(obj.src));
} }
} }

View File

@ -33,6 +33,8 @@ var PlatformJson = require('cordova-common').PlatformJson;
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger; var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
var PluginInfoProvider = require('cordova-common').PluginInfoProvider; var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
const GradlePropertiesParser = require('./config/GradlePropertiesParser');
module.exports.prepare = function (cordovaProject, options) { module.exports.prepare = function (cordovaProject, options) {
var self = this; var self = this;
@ -41,6 +43,15 @@ module.exports.prepare = function (cordovaProject, options) {
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations); this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
// Get the min SDK version from config.xml
const minSdkVersion = this._config.getPreference('android-minSdkVersion', 'android');
let gradlePropertiesUserConfig = {};
if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = minSdkVersion;
let gradlePropertiesParser = new GradlePropertiesParser(this.locations.root);
gradlePropertiesParser.configure(gradlePropertiesUserConfig);
// Update own www dir with project's www assets and plugins' assets and js-files // Update own www dir with project's www assets and plugins' assets and js-files
return Q.when(updateWww(cordovaProject, this.locations)).then(function () { return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
// update project according to config.xml changes. // update project according to config.xml changes.
@ -178,7 +189,7 @@ function updateProjectAccordingTo (platformConfig, locations) {
strings.find('string[@name="launcher_name"]').text = shortName.replace(/\'/g, '\\\''); strings.find('string[@name="launcher_name"]').text = shortName.replace(/\'/g, '\\\'');
} }
fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8'); fs.writeFileSync(locations.strings, strings.write({ indent: 4 }), 'utf-8');
events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings); events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings);
// Java packages cannot support dashes // Java packages cannot support dashes
@ -265,6 +276,14 @@ function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
return resourcePath; return resourcePath;
} }
function getAdaptiveImageResourcePath (resourcesDir, type, density, name, sourceName) {
if (/\.9\.png$/.test(sourceName)) {
name = name.replace(/\.png$/, '.9.png');
}
var resourcePath = path.join(resourcesDir, (density ? type + '-' + density + '-v26' : type), name);
return resourcePath;
}
function updateSplashes (cordovaProject, platformResourcesDir) { function updateSplashes (cordovaProject, platformResourcesDir) {
var resources = cordovaProject.projectConfig.getSplashScreens('android'); var resources = cordovaProject.projectConfig.getSplashScreens('android');
@ -314,20 +333,197 @@ function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
} }
function updateIcons (cordovaProject, platformResourcesDir) { function updateIcons (cordovaProject, platformResourcesDir) {
var icons = cordovaProject.projectConfig.getIcons('android'); let icons = cordovaProject.projectConfig.getIcons('android');
// if there are icon elements in config.xml // Skip if there are no app defined icons in config.xml
if (icons.length === 0) { if (icons.length === 0) {
events.emit('verbose', 'This app does not have launcher icons defined'); events.emit('verbose', 'This app does not have launcher icons defined');
return; return;
} }
var resourceMap = mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'icon.png'); // 1. loop icons determin if there is an error in the setup.
// 2. during initial loop, also setup for legacy support.
let errorMissingAttributes = [];
let errorLegacyIconNeeded = [];
let hasAdaptive = false;
icons.forEach((icon, key) => {
if (
(icon.background && !icon.foreground)
|| (!icon.background && icon.foreground)
|| (!icon.background && !icon.foreground && !icon.src)
) {
errorMissingAttributes.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
}
var android_icons = {}; if (icon.foreground) {
var default_icon; hasAdaptive = true;
if (
!icon.src
&& (
icon.foreground.startsWith('@color')
|| path.extname(path.basename(icon.foreground)) === '.xml'
)
) {
errorLegacyIconNeeded.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
} else if (!icon.src) {
icons[key].src = icon.foreground;
}
}
});
let errorMessage = [];
if (errorMissingAttributes.length > 0) {
errorMessage.push('One of the following attributes are set but missing the other for the density type: ' + errorMissingAttributes.join(', ') + '. Please ensure that all require attributes are defined.');
}
if (errorLegacyIconNeeded.length > 0) {
errorMessage.push('For the following icons with the density of: ' + errorLegacyIconNeeded.join(', ') + ', adaptive foreground with a defined color or vector can not be used as a standard fallback icon for older Android devices. To support older Android environments, please provide a value for the src attribute.');
}
if (errorMessage.length > 0) {
throw new CordovaError(errorMessage.join(' '));
}
let resourceMap = Object.assign(
{},
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
);
let preparedIcons = prepareIcons(icons);
if (hasAdaptive) {
resourceMap = updateIconResourceForAdaptive(preparedIcons, resourceMap, platformResourcesDir);
}
resourceMap = updateIconResourceForLegacy(preparedIcons, resourceMap, platformResourcesDir);
events.emit('verbose', 'Updating icons at ' + platformResourcesDir);
FileUpdater.updatePaths(resourceMap, { rootDir: cordovaProject.root }, logFileOp);
}
function updateIconResourceForAdaptive (preparedIcons, resourceMap, platformResourcesDir) {
let android_icons = preparedIcons.android_icons;
let default_icon = preparedIcons.default_icon;
// The source paths for icons and splashes are relative to
// project's config.xml location, so we use it as base path.
let background;
let foreground;
let targetPathBackground;
let targetPathForeground;
for (let density in android_icons) {
let backgroundVal = '@mipmap/ic_launcher_background';
let foregroundVal = '@mipmap/ic_launcher_foreground';
background = android_icons[density].background;
foreground = android_icons[density].foreground;
if (background.startsWith('@color')) {
// Colors Use Case
backgroundVal = background; // Example: @color/background_foobar_1
} else if (path.extname(path.basename(background)) === '.xml') {
// Vector Use Case
targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.xml', path.basename(android_icons[density].background));
resourceMap[targetPathBackground] = android_icons[density].background;
} else if (path.extname(path.basename(background)) === '.png') {
// Images Use Case
targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.png', path.basename(android_icons[density].background));
resourceMap[targetPathBackground] = android_icons[density].background;
}
if (foreground.startsWith('@color')) {
// Colors Use Case
foregroundVal = foreground;
} else if (path.extname(path.basename(foreground)) === '.xml') {
// Vector Use Case
targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.xml', path.basename(android_icons[density].foreground));
resourceMap[targetPathForeground] = android_icons[density].foreground;
} else if (path.extname(path.basename(foreground)) === '.png') {
// Images Use Case
targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.png', path.basename(android_icons[density].foreground));
resourceMap[targetPathForeground] = android_icons[density].foreground;
}
// create an XML for DPI and set color
const icLauncherTemplate = `<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="` + backgroundVal + `" />
<foreground android:drawable="` + foregroundVal + `" />
</adaptive-icon>`;
let launcherXmlPath = path.join(platformResourcesDir, 'mipmap-' + density + '-v26', 'ic_launcher.xml');
// Remove the XML from the resourceMap so the file does not get removed.
delete resourceMap[launcherXmlPath];
fs.writeFileSync(path.resolve(launcherXmlPath), icLauncherTemplate);
}
// There's no "default" drawable, so assume default == mdpi.
if (default_icon && !android_icons.mdpi) {
let defaultTargetPathBackground;
let defaultTargetPathForeground;
if (background.startsWith('@color')) {
// Colors Use Case
targetPathBackground = default_icon.background;
} else if (path.extname(path.basename(background)) === '.xml') {
// Vector Use Case
defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.xml', path.basename(default_icon.background));
resourceMap[defaultTargetPathBackground] = default_icon.background;
} else if (path.extname(path.basename(background)) === '.png') {
// Images Use Case
defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.png', path.basename(default_icon.background));
resourceMap[defaultTargetPathBackground] = default_icon.background;
}
if (foreground.startsWith('@color')) {
// Colors Use Case
targetPathForeground = default_icon.foreground;
} else if (path.extname(path.basename(foreground)) === '.xml') {
// Vector Use Case
defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.xml', path.basename(default_icon.foreground));
resourceMap[defaultTargetPathForeground] = default_icon.foreground;
} else if (path.extname(path.basename(foreground)) === '.png') {
// Images Use Case
defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.png', path.basename(default_icon.foreground));
resourceMap[defaultTargetPathForeground] = default_icon.foreground;
}
}
return resourceMap;
}
function updateIconResourceForLegacy (preparedIcons, resourceMap, platformResourcesDir) {
let android_icons = preparedIcons.android_icons;
let default_icon = preparedIcons.default_icon;
// The source paths for icons and splashes are relative to
// project's config.xml location, so we use it as base path.
for (var density in android_icons) {
var targetPath = getImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher.png', path.basename(android_icons[density].src));
resourceMap[targetPath] = android_icons[density].src;
}
// There's no "default" drawable, so assume default == mdpi.
if (default_icon && !android_icons.mdpi) {
var defaultTargetPath = getImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher.png', path.basename(default_icon.src));
resourceMap[defaultTargetPath] = default_icon.src;
}
return resourceMap;
}
function prepareIcons (icons) {
// http://developer.android.com/design/style/iconography.html // http://developer.android.com/design/style/iconography.html
var sizeToDensityMap = { const SIZE_TO_DENSITY_MAP = {
36: 'ldpi', 36: 'ldpi',
48: 'mdpi', 48: 'mdpi',
72: 'hdpi', 72: 'hdpi',
@ -335,11 +531,15 @@ function updateIcons (cordovaProject, platformResourcesDir) {
144: 'xxhdpi', 144: 'xxhdpi',
192: 'xxxhdpi' 192: 'xxxhdpi'
}; };
let android_icons = {};
let default_icon;
// find the best matching icon for a given density or size // find the best matching icon for a given density or size
// @output android_icons // @output android_icons
var parseIcon = function (icon, icon_size) { var parseIcon = function (icon, icon_size) {
// do I have a platform icon for that density already // do I have a platform icon for that density already
var density = icon.density || sizeToDensityMap[icon_size]; var density = icon.density || SIZE_TO_DENSITY_MAP[icon_size];
if (!density) { if (!density) {
// invalid icon defition ( or unsupported size) // invalid icon defition ( or unsupported size)
return; return;
@ -355,12 +555,34 @@ function updateIcons (cordovaProject, platformResourcesDir) {
for (var i = 0; i < icons.length; i++) { for (var i = 0; i < icons.length; i++) {
var icon = icons[i]; var icon = icons[i];
var size = icon.width; var size = icon.width;
if (!size) { if (!size) {
size = icon.height; size = icon.height;
} }
if (!size && !icon.density) { if (!size && !icon.density) {
if (default_icon) { if (default_icon) {
events.emit('verbose', 'Found extra default icon: ' + icon.src + ' (ignoring in favor of ' + default_icon.src + ')'); let found = {};
let favor = {};
// populating found icon.
if (icon.background && icon.foreground) {
found.background = icon.background;
found.foreground = icon.foreground;
}
if (icon.src) {
found.src = icon.src;
}
if (default_icon.background && default_icon.foreground) {
favor.background = default_icon.background;
favor.foreground = default_icon.foreground;
}
if (default_icon.src) {
favor.src = default_icon.src;
}
events.emit('verbose', 'Found extra default icon: ' + JSON.stringify(found) + ' and ignoring in favor of ' + JSON.stringify(favor) + '.');
} else { } else {
default_icon = icon; default_icon = icon;
} }
@ -369,36 +591,35 @@ function updateIcons (cordovaProject, platformResourcesDir) {
} }
} }
// The source paths for icons and splashes are relative to return {
// project's config.xml location, so we use it as base path. android_icons: android_icons,
for (var density in android_icons) { default_icon: default_icon
var targetPath = getImageResourcePath( };
platformResourcesDir, 'mipmap', density, 'icon.png', path.basename(android_icons[density].src));
resourceMap[targetPath] = android_icons[density].src;
}
// There's no "default" drawable, so assume default == mdpi.
if (default_icon && !android_icons.mdpi) {
var defaultTargetPath = getImageResourcePath(
platformResourcesDir, 'mipmap', 'mdpi', 'icon.png', path.basename(default_icon.src));
resourceMap[defaultTargetPath] = default_icon.src;
}
events.emit('verbose', 'Updating icons at ' + platformResourcesDir);
FileUpdater.updatePaths(
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
} }
function cleanIcons (projectRoot, projectConfig, platformResourcesDir) { function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
var icons = projectConfig.getIcons('android'); var icons = projectConfig.getIcons('android');
if (icons.length > 0) {
var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'icon.png'); // Skip if there are no app defined icons in config.xml
if (icons.length === 0) {
events.emit('verbose', 'This app does not have launcher icons defined');
return;
}
let resourceMap = Object.assign(
{},
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
);
events.emit('verbose', 'Cleaning icons at ' + platformResourcesDir); events.emit('verbose', 'Cleaning icons at ' + platformResourcesDir);
// No source paths are specified in the map, so updatePaths() will delete the target files. // No source paths are specified in the map, so updatePaths() will delete the target files.
FileUpdater.updatePaths( FileUpdater.updatePaths(resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
}
} }
/** /**
@ -446,7 +667,7 @@ function cleanFileResources (projectRoot, projectConfig, platformDir) {
FileUpdater.updatePaths( FileUpdater.updatePaths(
resourceMap, { resourceMap, {
rootDir: projectRoot, all: true}, logFileOp); rootDir: projectRoot, all: true }, logFileOp);
} }
} }

View File

@ -19,8 +19,6 @@
under the License. under the License.
*/ */
/* jshint node: true */
'use strict'; 'use strict';
var events = require('cordova-common').events; var events = require('cordova-common').events;
@ -29,21 +27,20 @@ var events = require('cordova-common').events;
* Retry a promise-returning function a number of times, propagating its * Retry a promise-returning function a number of times, propagating its
* results on success or throwing its error on a failed final attempt. * results on success or throwing its error on a failed final attempt.
* *
* @arg {Number} attemts_left - The number of times to retry the passed call. * @arg {Number} attemptsLeft - The number of times to retry the passed call.
* @arg {Function} promiseFunction - A function that returns a promise. * @arg {Function} promiseFunction - A function that returns a promise.
* @arg {...} - Arguments to pass to promiseFunction. * @arg {...} - Arguments to pass to promiseFunction.
* *
* @returns {Promise} * @returns {Promise}
*/ */
module.exports.retryPromise = function (attemts_left, promiseFunction) { module.exports.retryPromise = function (attemptsLeft, promiseFunction) {
// NOTE: // NOTE:
// get all trailing arguments, by skipping the first two (attemts_left and // get all trailing arguments, by skipping the first two (attemptsLeft and
// promiseFunction) because they shouldn't get passed to promiseFunction // promiseFunction) because they shouldn't get passed to promiseFunction
var promiseFunctionArguments = Array.prototype.slice.call(arguments, 2); var promiseFunctionArguments = Array.prototype.slice.call(arguments, 2);
return promiseFunction.apply(undefined, promiseFunctionArguments).then( return promiseFunction.apply(undefined, promiseFunctionArguments).then(
// on success pass results through // on success pass results through
function onFulfilled (value) { function onFulfilled (value) {
return value; return value;
@ -51,17 +48,16 @@ module.exports.retryPromise = function (attemts_left, promiseFunction) {
// on rejection either retry, or throw the error // on rejection either retry, or throw the error
function onRejected (error) { function onRejected (error) {
attemptsLeft -= 1;
attemts_left -= 1; if (attemptsLeft < 1) {
if (attemts_left < 1) {
throw error; throw error;
} }
events.emit('verbose', 'A retried call failed. Retrying ' + attemts_left + ' more time(s).'); events.emit('verbose', 'A retried call failed. Retrying ' + attemptsLeft + ' more time(s).');
// retry call self again with the same arguments, except attemts_left is now lower // retry call self again with the same arguments, except attemptsLeft is now lower
var fullArguments = [attemts_left, promiseFunction].concat(promiseFunctionArguments); var fullArguments = [attemptsLeft, promiseFunction].concat(promiseFunctionArguments);
return module.exports.retryPromise.apply(undefined, fullArguments); return module.exports.retryPromise.apply(undefined, fullArguments);
} }
); );

View File

@ -19,10 +19,7 @@
under the License. under the License.
*/ */
/* jshint loopfunc:true */
var path = require('path'); var path = require('path');
var build = require('./build');
var emulator = require('./emulator'); var emulator = require('./emulator');
var device = require('./device'); var device = require('./device');
var Q = require('q'); var Q = require('q');
@ -52,6 +49,7 @@ function getInstallTarget (runOptions) {
* @return {Promise} * @return {Promise}
*/ */
module.exports.run = function (runOptions) { module.exports.run = function (runOptions) {
runOptions = runOptions || {};
var self = this; var self = this;
var install_target = getInstallTarget(runOptions); var install_target = getInstallTarget(runOptions);
@ -103,16 +101,17 @@ module.exports.run = function (runOptions) {
}); });
}); });
}).then(function (resolvedTarget) { }).then(function (resolvedTarget) {
// Better just call self.build, but we're doing some processing of return new Promise((resolve) => {
// build results (according to platformApi spec) so they are in different const builder = require('./builders/builders').getBuilder();
// format than emulator.install expects. const buildOptions = require('./build').parseBuildOptions(runOptions, null, self.root);
// TODO: Update emulator/device.install to handle this change resolve(builder.fetchBuildResults(buildOptions.buildType, buildOptions.arch));
return build.run.call(self, runOptions, resolvedTarget).then(function (buildResults) { }).then(function (buildResults) {
if (resolvedTarget && resolvedTarget.isEmulator) { if (resolvedTarget && resolvedTarget.isEmulator) {
return emulator.wait_for_boot(resolvedTarget.target).then(function () { return emulator.wait_for_boot(resolvedTarget.target).then(function () {
return emulator.install(resolvedTarget, buildResults); return emulator.install(resolvedTarget, buildResults);
}); });
} }
return device.install(resolvedTarget, buildResults); return device.install(resolvedTarget, buildResults);
}); });
}); });

View File

@ -19,12 +19,12 @@
under the License. under the License.
*/ */
var emulator = require('./emulator'), var emulator = require('./emulator');
args = process.argv; var args = process.argv;
var install_target; var install_target;
if(args.length > 2) { if (args.length > 2) {
if (args[2].substring(0, 9) == '--target=') { if (args[2].substring(0, 9) === '--target=') {
install_target = args[2].substring(9, args[2].length); install_target = args[2].substring(9, args[2].length);
} else { } else {
console.error('ERROR : argument \'' + args[2] + '\' not recognized.'); console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
@ -32,8 +32,7 @@ if(args.length > 2) {
} }
} }
emulator.start(install_target).done(null, function(err) { emulator.start(install_target).catch(function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -19,17 +19,17 @@
under the License. under the License.
*/ */
var log = require('./lib/log'), var log = require('./lib/log');
reqs = require('./lib/check_reqs'), var reqs = require('./lib/check_reqs');
args = process.argv; var args = process.argv;
// Usage support for when args are given // Usage support for when args are given
if(args.length > 2) { if (args.length > 2) {
log.help(); log.help();
} else { } else {
reqs.run().done(function() { reqs.run().done(function () {
return log.run(); return log.run();
}, function(err) { }, function (err) {
console.error('ERROR: ' + err); console.error('ERROR: ' + err);
process.exit(2); process.exit(2);
}); });

View File

@ -24,22 +24,23 @@ var nopt = require('nopt');
var path = require('path'); var path = require('path');
// Support basic help commands // Support basic help commands
if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
require('./lib/run').help(); require('./lib/run').help();
}
// Do some basic argument parsing // Do some basic argument parsing
var runOpts = nopt({ var runOpts = nopt({
'verbose' : Boolean, 'verbose': Boolean,
'silent' : Boolean, 'silent': Boolean,
'debug' : Boolean, 'debug': Boolean,
'release' : Boolean, 'release': Boolean,
'nobuild': Boolean, 'nobuild': Boolean,
'buildConfig' : path, 'buildConfig': path,
'archs' : String, 'archs': String,
'device' : Boolean, 'device': Boolean,
'emulator': Boolean, 'emulator': Boolean,
'target' : String 'target': String
}, { 'd' : '--verbose' }); }, { 'd': '--verbose' });
// Make runOptions compatible with PlatformApi run method spec // Make runOptions compatible with PlatformApi run method spec
runOpts.argv = runOpts.argv.remain; runOpts.argv = runOpts.argv.remain;
@ -47,7 +48,7 @@ runOpts.argv = runOpts.argv.remain;
require('./loggingHelper').adjustLoggerLevel(runOpts); require('./loggingHelper').adjustLoggerLevel(runOpts);
new Api().run(runOpts) new Api().run(runOpts)
.catch(function(err) { .catch(function (err) {
console.error(err, err.stack); console.error(err, err.stack);
process.exit(2); process.exit(2);
}); });

View File

@ -20,7 +20,7 @@
*/ */
// Coho updates this line: // Coho updates this line:
var VERSION = "7.1.4"; var VERSION = "8.0.0";
module.exports.version = VERSION; module.exports.version = VERSION;

View File

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

View File

@ -22,33 +22,32 @@ apply plugin: 'com.android.application'
buildscript { buildscript {
repositories { repositories {
mavenCentral() mavenCentral()
maven { google()
url "https://maven.google.com"
}
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.3.0'
} }
} }
// Allow plugins to declare Maven dependencies via build-extras.gradle. // Allow plugins to declare Maven dependencies via build-extras.gradle.
allprojects { allprojects {
repositories { repositories {
mavenCentral(); mavenCentral()
jcenter() jcenter()
} }
} }
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = '4.1.0' gradleVersion = '4.10.3'
} }
// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties. // Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html // Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext { ext {
apply from: '../CordovaLib/cordova.gradle' apply from: '../CordovaLib/cordova.gradle'
// The value for android.compileSdkVersion. // The value for android.compileSdkVersion.
if (!project.hasProperty('cdvCompileSdkVersion')) { if (!project.hasProperty('cdvCompileSdkVersion')) {
cdvCompileSdkVersion = null; cdvCompileSdkVersion = null;
@ -145,7 +144,8 @@ cdvBuildRelease.dependsOn {
return computeBuildTargetName(false) return computeBuildTargetName(false)
} }
task cdvPrintProps << { task cdvPrintProps {
doLast {
println('cdvCompileSdkVersion=' + cdvCompileSdkVersion) println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
println('cdvBuildToolsVersion=' + cdvBuildToolsVersion) println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
println('cdvVersionCode=' + cdvVersionCode) println('cdvVersionCode=' + cdvVersionCode)
@ -159,10 +159,10 @@ task cdvPrintProps << {
android.productFlavors.each { flavor -> android.productFlavors.each { flavor ->
println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode) println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
} }
}
} }
android { android {
defaultConfig { defaultConfig {
versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode")) versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
applicationId privateHelpers.extractStringFromManifest("package") applicationId privateHelpers.extractStringFromManifest("package")
@ -249,6 +249,7 @@ android {
} }
addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release) addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
} }
if (cdvDebugSigningPropertiesFile) { if (cdvDebugSigningPropertiesFile) {
addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug) addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
} }

View File

@ -1,5 +1,5 @@
// Platform: android // Platform: android
// 9e8e1b716252c4a08abcd31a13013b868d6f4141 // 882658ab17740dbdece764e68c1f1f1f44fe3f9d
/* /*
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -19,12 +19,9 @@
under the License. under the License.
*/ */
;(function() { ;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '7.1.4'; var PLATFORM_VERSION_BUILD_LABEL = '8.0.0';
// file: src/scripts/require.js // file: src/scripts/require.js
/* jshint -W079 */
/* jshint -W020 */
var require; var require;
var define; var define;
@ -327,7 +324,7 @@ module.exports = cordova;
}); });
// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js // file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
define("cordova/android/nativeapiprovider", function(require, exports, module) { define("cordova/android/nativeapiprovider", function(require, exports, module) {
/** /**
@ -350,7 +347,7 @@ module.exports = {
}); });
// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js // file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
define("cordova/android/promptbasednativeapi", function(require, exports, module) { define("cordova/android/promptbasednativeapi", function(require, exports, module) {
/** /**
@ -882,7 +879,7 @@ module.exports = channel;
}); });
// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/exec.js // file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/exec.js
define("cordova/exec", function(require, exports, module) { define("cordova/exec", function(require, exports, module) {
/** /**
@ -975,17 +972,6 @@ function androidExec(success, fail, service, action, args) {
} }
androidExec.init = function() { androidExec.init = function() {
//CB-11828
//This failsafe checks the version of Android and if it's Jellybean, it switches it to
//using the Online Event bridge for communicating from Native to JS
//
//It's ugly, but it's necessary.
var check = navigator.userAgent.toLowerCase().match(/android\s[0-9].[0-9]/);
var version_code = check && check[0].match(/4.[0-3].*/);
if (version_code != null && nativeToJsBridgeMode == nativeToJsModes.EVAL_BRIDGE) {
nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;
}
bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode); bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
channel.onNativeReady.fire(); channel.onNativeReady.fire();
}; };
@ -1320,130 +1306,6 @@ channel.join(function () {
}); });
// file: src/common/init_b.js
define("cordova/init_b", function(require, exports, module) {
var channel = require('cordova/channel');
var cordova = require('cordova');
var modulemapper = require('cordova/modulemapper');
var platform = require('cordova/platform');
var pluginloader = require('cordova/pluginloader');
var utils = require('cordova/utils');
var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
// setting exec
cordova.exec = require('cordova/exec');
function logUnfiredChannels (arr) {
for (var i = 0; i < arr.length; ++i) {
if (arr[i].state !== 2) {
console.log('Channel not fired: ' + arr[i].type);
}
}
}
window.setTimeout(function () {
if (channel.onDeviceReady.state !== 2) {
console.log('deviceready has not fired after 5 seconds.');
logUnfiredChannels(platformInitChannelsArray);
logUnfiredChannels(channel.deviceReadyChannelsArray);
}
}, 5000);
// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
// We replace it so that properties that can't be clobbered can instead be overridden.
function replaceNavigator (origNavigator) {
var CordovaNavigator = function () {};
CordovaNavigator.prototype = origNavigator;
var newNavigator = new CordovaNavigator();
// This work-around really only applies to new APIs that are newer than Function.bind.
// Without it, APIs such as getGamepads() break.
if (CordovaNavigator.bind) {
for (var key in origNavigator) {
if (typeof origNavigator[key] === 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator);
} else {
(function (k) {
utils.defineGetterSetter(newNavigator, key, function () {
return origNavigator[k];
});
})(key);
}
}
}
return newNavigator;
}
if (window.navigator) {
window.navigator = replaceNavigator(window.navigator);
}
if (!window.console) {
window.console = {
log: function () {}
};
}
if (!window.console.warn) {
window.console.warn = function (msg) {
this.log('warn: ' + msg);
};
}
// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onActivated = cordova.addDocumentEventHandler('activated');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
// Listen for DOMContentLoaded and notify our channel subscribers.
if (document.readyState === 'complete' || document.readyState === 'interactive') {
channel.onDOMContentLoaded.fire();
} else {
document.addEventListener('DOMContentLoaded', function () {
channel.onDOMContentLoaded.fire();
}, false);
}
// _nativeReady is global variable that the native side can set
// to signify that the native code is ready. It is a global since
// it may be called before any cordova JS is ready.
if (window._nativeReady) {
channel.onNativeReady.fire();
}
// Call the platform-specific initialization.
platform.bootstrap && platform.bootstrap();
// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
// The delay allows the attached modules to be defined before the plugin loader looks for them.
setTimeout(function () {
pluginloader.load(function () {
channel.onPluginsReady.fire();
});
}, 0);
/**
* Create all cordova objects once native side is ready.
*/
channel.join(function () {
modulemapper.mapModules(window);
platform.initialize && platform.initialize();
// Fire event to notify that all objects are created
channel.onCordovaReady.fire();
// Fire onDeviceReady event once page has fully loaded, all
// constructors have run and cordova info has been received from native
// side.
channel.join(function () {
require('cordova').fireDocumentEvent('deviceready');
}, channel.deviceReadyChannelsArray);
}, platformInitChannelsArray);
});
// file: src/common/modulemapper.js // file: src/common/modulemapper.js
define("cordova/modulemapper", function(require, exports, module) { define("cordova/modulemapper", function(require, exports, module) {
@ -1544,103 +1406,7 @@ exports.reset();
}); });
// file: src/common/modulemapper_b.js // file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/platform.js
define("cordova/modulemapper_b", function(require, exports, module) {
var builder = require('cordova/builder');
var symbolList = [];
var deprecationMap;
exports.reset = function () {
symbolList = [];
deprecationMap = {};
};
function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
symbolList.push(strategy, moduleName, symbolPath);
if (opt_deprecationMessage) {
deprecationMap[symbolPath] = opt_deprecationMessage;
}
}
// Note: Android 2.3 does have Function.bind().
exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
};
exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
};
exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
};
exports.runs = function (moduleName) {
addEntry('r', moduleName, null);
};
function prepareNamespace (symbolPath, context) {
if (!symbolPath) {
return context;
}
var parts = symbolPath.split('.');
var cur = context;
for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
cur = cur[part] = cur[part] || {};
}
return cur;
}
exports.mapModules = function (context) {
var origSymbols = {};
context.CDV_origSymbols = origSymbols;
for (var i = 0, len = symbolList.length; i < len; i += 3) {
var strategy = symbolList[i];
var moduleName = symbolList[i + 1];
var module = require(moduleName);
// <runs/>
if (strategy === 'r') {
continue;
}
var symbolPath = symbolList[i + 2];
var lastDot = symbolPath.lastIndexOf('.');
var namespace = symbolPath.substr(0, lastDot);
var lastName = symbolPath.substr(lastDot + 1);
var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
var parentObj = prepareNamespace(namespace, context);
var target = parentObj[lastName];
if (strategy === 'm' && target) {
builder.recursiveMerge(target, module);
} else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
if (!(symbolPath in origSymbols)) {
origSymbols[symbolPath] = target;
}
builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
}
}
};
exports.getOriginalSymbol = function (context, symbolPath) {
var origSymbols = context.CDV_origSymbols;
if (origSymbols && (symbolPath in origSymbols)) {
return origSymbols[symbolPath];
}
var parts = symbolPath.split('.');
var obj = context;
for (var i = 0; i < parts.length; ++i) {
obj = obj && obj[parts[i]];
}
return obj;
};
exports.reset();
});
// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/platform.js
define("cordova/platform", function(require, exports, module) { define("cordova/platform", function(require, exports, module) {
// The last resume event that was received that had the result of a plugin call. // The last resume event that was received that had the result of a plugin call.
@ -1750,7 +1516,7 @@ function onMessageFromNative(msg) {
}); });
// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/plugin/android/app.js // file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) { define("cordova/plugin/android/app", function(require, exports, module) {
var exec = require('cordova/exec'); var exec = require('cordova/exec');
@ -1953,53 +1719,6 @@ exports.load = function (callback) {
}); });
// file: src/common/pluginloader_b.js
define("cordova/pluginloader_b", function(require, exports, module) {
var modulemapper = require('cordova/modulemapper');
// Handler for the cordova_plugins.js content.
// See plugman's plugin_loader.js for the details of this object.
function handlePluginsObject (moduleList) {
// if moduleList is not defined or empty, we've nothing to do
if (!moduleList || !moduleList.length) {
return;
}
// Loop through all the modules and then through their clobbers and merges.
for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
if (module.clobbers && module.clobbers.length) {
for (var j = 0; j < module.clobbers.length; j++) {
modulemapper.clobbers(module.id, module.clobbers[j]);
}
}
if (module.merges && module.merges.length) {
for (var k = 0; k < module.merges.length; k++) {
modulemapper.merges(module.id, module.merges[k]);
}
}
// Finally, if runs is truthy we want to simply require() the module.
if (module.runs) {
modulemapper.runs(module.id);
}
}
}
// Loads all plugins' js-modules. Plugin loading is syncronous in browserified bundle
// but the method accepts callback to be compatible with non-browserify flow.
// onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
// no plugins to load, or they are all done.
exports.load = function (callback) {
var moduleList = require('cordova/plugin_list');
handlePluginsObject(moduleList);
callback();
};
});
// file: src/common/urlutil.js // file: src/common/urlutil.js
define("cordova/urlutil", function(require, exports, module) { define("cordova/urlutil", function(require, exports, module) {

View File

@ -20,32 +20,30 @@
buildscript { buildscript {
repositories { repositories {
maven { google()
url "https://maven.google.com"
}
jcenter() jcenter()
} }
dependencies {
dependencies {
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.3.0'
} }
} }
allprojects { allprojects {
repositories { repositories {
maven { google()
url "https://maven.google.com"
}
jcenter() jcenter()
} }
//This replaces project.properties w.r.t. build settings //This replaces project.properties w.r.t. build settings
project.ext { project.ext {
defaultBuildToolsVersion="27.0.1" //String defaultBuildToolsVersion="28.0.3" //String
defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4 defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4
defaultTargetSdkVersion=27 //Integer - We ALWAYS target the latest by default defaultTargetSdkVersion=28 //Integer - We ALWAYS target the latest by default
defaultCompileSdkVersion=27 //Integer - We ALWAYS compile with the latest by default defaultCompileSdkVersion=28 //Integer - We ALWAYS compile with the latest by default
} }
} }

View File

@ -10,5 +10,12 @@ ant-gen
# Eclipse builds # Eclipse builds
gen gen
out out
# Gradle builds # Gradle build artifacts
.gradle
.gradletasknamecache
/build /build
/CordovaLib/build
/app/build
gradle-app.setting
# Android Studio
.idea

View File

@ -245,7 +245,7 @@ android {
} }
dependencies { dependencies {
compile fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
// SUB-PROJECT DEPENDENCIES START // SUB-PROJECT DEPENDENCIES START
// SUB-PROJECT DEPENDENCIES END // SUB-PROJECT DEPENDENCIES END
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -24,7 +24,7 @@ var args = require('nopt')({
'link': Boolean, 'link': Boolean,
'shared': Boolean, 'shared': Boolean,
'help': Boolean 'help': Boolean
}, { 'd' : '--verbose' }); }, { 'd': '--verbose' });
if (args.help || args.argv.remain.length === 0) { if (args.help || args.argv.remain.length === 0) {
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]'); console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]');
@ -34,4 +34,4 @@ if (args.help || args.argv.remain.length === 0) {
require('./templates/cordova/loggingHelper').adjustLoggerLevel(args); require('./templates/cordova/loggingHelper').adjustLoggerLevel(args);
Api.updatePlatform(args.argv.remain[0], {link: (args.link || args.shared)}).done(); Api.updatePlatform(args.argv.remain[0], { link: (args.link || args.shared) }).done();

View File

@ -24,15 +24,15 @@ ext {
buildscript { buildscript {
repositories { repositories {
maven { google()
url "https://maven.google.com"
}
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' // The gradle plugin and the maven plugin have to be updated after each version of Android
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' // studio comes out
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
} }
} }
@ -42,12 +42,11 @@ apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray' apply plugin: 'com.jfrog.bintray'
group = 'org.apache.cordova' group = 'org.apache.cordova'
version = '7.1.4' version = '8.0.0'
android { android {
compileSdkVersion cdvCompileSdkVersion compileSdkVersion cdvCompileSdkVersion
buildToolsVersion cdvBuildToolsVersion buildToolsVersion cdvBuildToolsVersion
publishNonDefault true
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -94,9 +93,9 @@ install {
} }
} }
scm { scm {
connection 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git' connection 'scm:git:https://github.com/apache/cordova-android.git'
developerConnection 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git' developerConnection 'scm:git:git@github.com:apache/cordova-android.git'
url 'https://git-wip-us.apache.org/repos/asf?p=cordova-android' url 'https://github.com/apache/cordova-android'
} }
} }
@ -122,16 +121,16 @@ bintray {
name = 'cordova-android' name = 'cordova-android'
userOrg = 'cordova' userOrg = 'cordova'
licenses = ['Apache-2.0'] licenses = ['Apache-2.0']
vcsUrl = 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git' vcsUrl = 'https://github.com/apache/cordova-android'
websiteUrl = 'https://cordova.apache.org' websiteUrl = 'https://cordova.apache.org'
issueTrackerUrl = 'https://issues.apache.org/jira/browse/CB' issueTrackerUrl = 'https://github.com/apache/cordova-android/issues'
publicDownloadNumbers = true publicDownloadNumbers = true
licenses = ['Apache-2.0'] licenses = ['Apache-2.0']
labels = ['android', 'cordova', 'phonegap'] labels = ['android', 'cordova', 'phonegap']
version { version {
name = '7.1.4' name = '8.0.0'
released = new Date() released = new Date()
vcsTag = '7.1.4' vcsTag = '8.0.0'
} }
} }
} }

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

View File

@ -1,16 +1,11 @@
# This file is automatically generated by Android Tools. # This file was originally created by the Android Tools, but is now
# Do not modify this file -- YOUR CHANGES WILL BE ERASED! # used by cordova-android to manage the project configuration.
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=android-27 target=android-28
apk-configurations= apk-configurations=
renderscript.opt.level=O0 renderscript.opt.level=O0
android.library=true android.library=true

View File

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

View File

@ -216,8 +216,10 @@ public class CordovaWebViewImpl implements CordovaWebView {
// TODO: What about params? // TODO: What about params?
// Load new URL // Load new URL
loadUrlIntoView(url, true); loadUrlIntoView(url, true);
return;
} else { } else {
LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the <allow-navigation> whitelist. URL=" + url); LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the <allow-navigation> whitelist. URL=" + url);
return;
} }
} }
if (!pluginManager.shouldOpenExternalUrl(url)) { if (!pluginManager.shouldOpenExternalUrl(url)) {

View File

@ -43,6 +43,7 @@ public class CoreAndroid extends CordovaPlugin {
private BroadcastReceiver telephonyReceiver; private BroadcastReceiver telephonyReceiver;
private CallbackContext messageChannel; private CallbackContext messageChannel;
private PluginResult pendingResume; private PluginResult pendingResume;
private PluginResult pendingPause;
private final Object messageChannelLock = new Object(); private final Object messageChannelLock = new Object();
/** /**
@ -113,6 +114,10 @@ public class CoreAndroid extends CordovaPlugin {
else if (action.equals("messageChannel")) { else if (action.equals("messageChannel")) {
synchronized(messageChannelLock) { synchronized(messageChannelLock) {
messageChannel = callbackContext; messageChannel = callbackContext;
if (pendingPause != null) {
sendEventMessage(pendingPause);
pendingPause = null;
}
if (pendingResume != null) { if (pendingResume != null) {
sendEventMessage(pendingResume); sendEventMessage(pendingResume);
pendingResume = null; pendingResume = null;
@ -139,7 +144,7 @@ public class CoreAndroid extends CordovaPlugin {
public void clearCache() { public void clearCache() {
cordova.getActivity().runOnUiThread(new Runnable() { cordova.getActivity().runOnUiThread(new Runnable() {
public void run() { public void run() {
webView.clearCache(true); webView.clearCache();
} }
}); });
} }
@ -321,7 +326,19 @@ public class CoreAndroid extends CordovaPlugin {
} catch (JSONException e) { } catch (JSONException e) {
LOG.e(TAG, "Failed to create event message", e); LOG.e(TAG, "Failed to create event message", e);
} }
sendEventMessage(new PluginResult(PluginResult.Status.OK, obj)); PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
if (messageChannel == null) {
LOG.i(TAG, "Request to send event before messageChannel initialised: " + action);
if ("pause".equals(action)) {
pendingPause = result;
} else if ("resume".equals(action)) {
// When starting normally onPause then onResume is called
pendingPause = null;
}
} else {
sendEventMessage(result);
}
} }
private void sendEventMessage(PluginResult payload) { private void sendEventMessage(PluginResult payload) {

View File

@ -58,8 +58,12 @@ class SystemCookieManager implements ICordovaCookieManager {
} }
public void clearCookies() { public void clearCookies() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.removeAllCookies(null);
} else {
cookieManager.removeAllCookie(); cookieManager.removeAllCookie();
} }
}
public void flush() { public void flush() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

View File

@ -142,6 +142,7 @@ public class SystemWebChromeClient extends WebChromeClient {
* Handle database quota exceeded notification. * Handle database quota exceeded notification.
*/ */
@Override @Override
@SuppressWarnings("deprecation")
public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
{ {
@ -180,11 +181,13 @@ public class SystemWebChromeClient extends WebChromeClient {
// API level 7 is required for this, see if we could lower this using something else // API level 7 is required for this, see if we could lower this using something else
@Override @Override
@SuppressWarnings("deprecation")
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) { public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
parentEngine.getCordovaWebView().showCustomView(view, callback); parentEngine.getCordovaWebView().showCustomView(view, callback);
} }
@Override @Override
@SuppressWarnings("deprecation")
public void onHideCustomView() { public void onHideCustomView() {
parentEngine.getCordovaWebView().hideCustomView(); parentEngine.getCordovaWebView().hideCustomView();
} }

View File

@ -75,6 +75,7 @@ public class SystemWebViewClient extends WebViewClient {
* @return true to override, false for default behavior * @return true to override, false for default behavior
*/ */
@Override @Override
@SuppressWarnings("deprecation")
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
return parentEngine.client.onNavigationAttempt(url); return parentEngine.client.onNavigationAttempt(url);
} }
@ -186,6 +187,7 @@ public class SystemWebViewClient extends WebViewClient {
* @param failingUrl The url that failed to load. * @param failingUrl The url that failed to load.
*/ */
@Override @Override
@SuppressWarnings("deprecation")
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// Ignore error due to stopLoading(). // Ignore error due to stopLoading().
if (!isCurrentlyLoading) { if (!isCurrentlyLoading) {
@ -316,6 +318,7 @@ public class SystemWebViewClient extends WebViewClient {
} }
@Override @Override
@SuppressWarnings("deprecation")
public WebResourceResponse shouldInterceptRequest(WebView view, String url) { public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
try { try {
// Check the against the whitelist and lock out access to the WebView directory // Check the against the whitelist and lock out access to the WebView directory

View File

@ -1 +0,0 @@
../nopt/bin/nopt.js

View File

@ -1 +0,0 @@
../semver/bin/semver

View File

@ -1 +0,0 @@
../shelljs/bin/shjs

View File

@ -1,46 +0,0 @@
This software is dual-licensed under the ISC and MIT licenses.
You may use this software under EITHER of the following licenses.
----------
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------
Copyright Isaac Z. Schlueter and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,23 +0,0 @@
# abbrev-js
Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
Usage:
var abbrev = require("abbrev");
abbrev("foo", "fool", "folding", "flop");
// returns:
{ fl: 'flop'
, flo: 'flop'
, flop: 'flop'
, fol: 'folding'
, fold: 'folding'
, foldi: 'folding'
, foldin: 'folding'
, folding: 'folding'
, foo: 'foo'
, fool: 'fool'
}
This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.

View File

@ -1,61 +0,0 @@
module.exports = exports = abbrev.abbrev = abbrev
abbrev.monkeyPatch = monkeyPatch
function monkeyPatch () {
Object.defineProperty(Array.prototype, 'abbrev', {
value: function () { return abbrev(this) },
enumerable: false, configurable: true, writable: true
})
Object.defineProperty(Object.prototype, 'abbrev', {
value: function () { return abbrev(Object.keys(this)) },
enumerable: false, configurable: true, writable: true
})
}
function abbrev (list) {
if (arguments.length !== 1 || !Array.isArray(list)) {
list = Array.prototype.slice.call(arguments, 0)
}
for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
}
// sort them lexicographically, so that they're next to their nearest kin
args = args.sort(lexSort)
// walk through each, seeing how much it has in common with the next and previous
var abbrevs = {}
, prev = ""
for (var i = 0, l = args.length ; i < l ; i ++) {
var current = args[i]
, next = args[i + 1] || ""
, nextMatches = true
, prevMatches = true
if (current === next) continue
for (var j = 0, cl = current.length ; j < cl ; j ++) {
var curChar = current.charAt(j)
nextMatches = nextMatches && curChar === next.charAt(j)
prevMatches = prevMatches && curChar === prev.charAt(j)
if (!nextMatches && !prevMatches) {
j ++
break
}
}
prev = current
if (j === cl) {
abbrevs[current] = current
continue
}
for (var a = current.substr(0, j) ; j <= cl ; j ++) {
abbrevs[a] = current
a += current.charAt(j)
}
}
return abbrevs
}
function lexSort (a, b) {
return a === b ? 0 : a > b ? 1 : -1
}

View File

@ -1,57 +0,0 @@
{
"_from": "abbrev@1",
"_id": "abbrev@1.1.1",
"_inBundle": true,
"_integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"_location": "/cordova-android/abbrev",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "abbrev@1",
"name": "abbrev",
"escapedName": "abbrev",
"rawSpec": "1",
"saveSpec": null,
"fetchSpec": "1"
},
"_requiredBy": [
"/cordova-android",
"/cordova-android/nopt"
],
"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"_shasum": "f8f2c887ad10bf67f634f005b6987fed3179aac8",
"_spec": "abbrev@1",
"_where": "/Users/brodybits/Documents/cordova/cordova-android/node_modules/nopt",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me"
},
"bugs": {
"url": "https://github.com/isaacs/abbrev-js/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Like ruby's abbrev module, but in js",
"devDependencies": {
"tap": "^10.1"
},
"files": [
"abbrev.js"
],
"homepage": "https://github.com/isaacs/abbrev-js#readme",
"license": "ISC",
"main": "abbrev.js",
"name": "abbrev",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
},
"scripts": {
"postpublish": "git push origin --all; git push origin --tags",
"postversion": "npm publish",
"preversion": "npm test",
"test": "tap test.js --100"
},
"version": "1.1.1"
}

View File

@ -1,8 +0,0 @@
.git/
node_modules/
coverage/
build/
assets/
dist/
docs/
tests/

View File

@ -1,29 +0,0 @@
{
"esversion": 6,
"indent": 2,
"forin": true,
"noarg": true,
"bitwise": true,
"nonew": true,
"strict": true,
"browser": true,
"devel": true,
"node": false,
"jquery": false,
"esnext": false,
"moz": false,
"es3": false,
"asi": true,
"eqnull": true,
"debug": true,
"boss": true,
"evil": true,
"loopfunc": true,
"laxbreak": true,
"unused": true,
"undef": true
}

View File

@ -1,3 +0,0 @@
language: node_js
node_js:
- "6.1.0"

View File

@ -1,87 +0,0 @@
Android Versions
================
A node module to get Android versions by API level, NDK level, semantic version, or version name.
Versions are referenced from [source.android.com/source/build-numbers.html](https://source.android.com/source/build-numbers.html#platform-code-names-versions-api-levels-and-ndk-releases). The version for "Current Development Build" (`"CUR_DEVELOPMENT"`) is not included in the list of `VERSIONS`.
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[npm-image]: https://img.shields.io/npm/v/android-versions.svg?style=flat-square
[npm-url]: https://npmjs.org/package/android-versions
[travis-image]: https://img.shields.io/travis/dvoiss/android-versions.svg?style=flat-square
[travis-url]: https://travis-ci.org/dvoiss/android-versions
## Install
```bash
# NPM
npm install android-versions --save
# YARN
yarn add android-versions
```
## Usage
View the tests for more advanced usage.
```javascript
const android = require('android-versions')
```
#### Get by API level:
```javascript
console.log(android.get(23))
=> { api: 23, ndk: 8, semver: "6.0", name: "Marshmallow", versionCode: "M" }
```
#### Get by version:
```javascript
console.log(android.get("2.3.3"))
=> { api: 10, ndk: 5, semver: "2.3.3", name: "Gingerbread", versionCode: "GINGERBREAD_MR1" }
```
#### Get all by predicate:
```
android.getAll((version) => {
return version.ndk > 5 && version.api < 15
}).map((version) => version.versionCode)
=> [ "HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH" ]
```
#### Access a specific version with all info:
```
android.LOLLIPOP
=> { api: 21, ndk: 8, semver: "5.0", name: "Lollipop", versionCode: "LOLLIPOP" }
```
#### Access the complete reference of Android versions with all info:
```javascript
android.VERSIONS
=> {
BASE: { api: 1, ndk: 0, semver: "1.0", name: "(no code name)", versionCode: "BASE" },
...
N: { api: 24, ndk: 8, semver: "7.0", name: "Nougat", versionCode: "N" }
...
}
```
## Test
```bash
npm run test
```
## License
MIT

View File

@ -1,161 +0,0 @@
/**
* Copyright (c) 2016, David Voiss <davidvoiss@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
/* jshint node: true */
"use strict";
/**
* A module to get Android versions by API level, NDK level, semantic version, or version name.
*
* Versions are referenced from here:
* {@link https://source.android.com/source/build-numbers.html#platform-code-names-versions-api-levels-and-ndk-releases}
* {@link https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/Build.java}
*
* The version for "Current Development Build" ("CUR_DEVELOPMENT") is not included.
*
* @module android-versions
*/
var VERSIONS = {
BASE: { api: 1, ndk: 0, semver: "1.0", name: "(no code name)", },
BASE_1_1: { api: 2, ndk: 0, semver: "1.1", name: "(no code name)", },
CUPCAKE: { api: 3, ndk: 1, semver: "1.5", name: "Cupcake", },
DONUT: { api: 4, ndk: 2, semver: "1.6", name: "Donut", },
ECLAIR: { api: 5, ndk: 2, semver: "2.0", name: "Eclair", },
ECLAIR_0_1: { api: 6, ndk: 2, semver: "2.0.1", name: "Eclair", },
ECLAIR_MR1: { api: 7, ndk: 3, semver: "2.1", name: "Eclair", },
FROYO: { api: 8, ndk: 4, semver: "2.2.x", name: "Froyo", },
GINGERBREAD: { api: 9, ndk: 5, semver: "2.3.0 - 2.3.2", name: "Gingerbread", },
GINGERBREAD_MR1: { api: 10, ndk: 5, semver: "2.3.3 - 2.3.7", name: "Gingerbread", },
HONEYCOMB: { api: 11, ndk: 5, semver: "3.0", name: "Honeycomb", },
HONEYCOMB_MR1: { api: 12, ndk: 6, semver: "3.1", name: "Honeycomb", },
HONEYCOMB_MR2: { api: 13, ndk: 6, semver: "3.2.x", name: "Honeycomb", },
ICE_CREAM_SANDWICH: { api: 14, ndk: 7, semver: "4.0.1 - 4.0.2", name: "Ice Cream Sandwich", },
ICE_CREAM_SANDWICH_MR1: { api: 15, ndk: 8, semver: "4.0.3 - 4.0.4", name: "Ice Cream Sandwich", },
JELLY_BEAN: { api: 16, ndk: 8, semver: "4.1.x", name: "Jellybean", },
JELLY_BEAN_MR1: { api: 17, ndk: 8, semver: "4.2.x", name: "Jellybean", },
JELLY_BEAN_MR2: { api: 18, ndk: 8, semver: "4.3.x", name: "Jellybean", },
KITKAT: { api: 19, ndk: 8, semver: "4.4.0 - 4.4.4", name: "KitKat", },
KITKAT_WATCH: { api: 20, ndk: 8, semver: "4.4", name: "KitKat Watch", },
LOLLIPOP: { api: 21, ndk: 8, semver: "5.0", name: "Lollipop", },
LOLLIPOP_MR1: { api: 22, ndk: 8, semver: "5.1", name: "Lollipop", },
M: { api: 23, ndk: 8, semver: "6.0", name: "Marshmallow", },
N: { api: 24, ndk: 8, semver: "7.0", name: "Nougat", },
N_MR1: { api: 25, ndk: 8, semver: "7.1", name: "Nougat", },
O: { api: 26, ndk: 8, semver: "8.0.0", name: "Oreo", },
O_MR1: { api: 27, ndk: 8, semver: "8.1.0", name: "Oreo", },
P: { api: 28, ndk: 8, semver: "9", name: "Pie", }
}
// Add a key to each version of Android for the "versionCode".
// This is the same key we use in the VERSIONS map above.
Object.keys(VERSIONS).forEach(function(version) {
VERSIONS[version].versionCode = version
})
var semver = require('semver');
// semver format requires <major>.<minor>.<patch> but we allow just <major>.<minor> format.
// Coerce <major>.<minor> to <major>.<minor>.0
function formatSemver(semver) {
if (semver.match(/^\d+.\d+$/)) {
return semver + '.0'
} else {
return semver
}
}
// The default predicate compares against API level, semver, name, or code.
function getFromDefaultPredicate(arg) {
// Coerce arg to string for comparisons below.
arg = arg.toString()
return getFromPredicate(function(version) {
// Check API level before all else.
if (arg === version.api.toString()) {
return true
}
var argSemver = formatSemver(arg)
var versionSemver = formatSemver(version.semver)
if (semver.valid(argSemver) && semver.satisfies(argSemver, versionSemver)) {
return true
}
// Compare version name and code.
return arg === version.name || arg === version.versionCode
})
}
// The function to allow passing a predicate.
function getFromPredicate(predicate) {
if (predicate === null) {
return null
}
return Object.keys(VERSIONS).filter(function(version) {
return predicate(VERSIONS[version])
}).map(function(key) { return VERSIONS[key] })
}
/**
* The Android version codes available as keys for easier look-up.
*/
Object.keys(VERSIONS).forEach(function(name) {
exports[name] = VERSIONS[name]
})
/**
* The complete reference of Android versions for easier look-up.
*/
exports.VERSIONS = VERSIONS
/**
* Retrieve a single Android version.
*
* @param {object | Function} arg - The value or predicate to use to retrieve values.
*
* @return {object} An object representing the version found or null if none found.
*/
exports.get = function(arg) {
var result = exports.getAll(arg)
if (result === null || result.length === 0) {
return null
}
return result[0]
}
/**
* Retrieve all Android versions that meet the criteria of the argument.
*
* @param {object | Function} arg - The value or predicate to use to retrieve values.
*
* @return {object} An object representing the version found or null if none found.
*/
exports.getAll = function(arg) {
if (arg === null) {
return null
}
if (typeof arg === "function") {
return getFromPredicate(arg)
} else {
return getFromDefaultPredicate(arg)
}
}

View File

@ -1,67 +0,0 @@
{
"_from": "android-versions@1",
"_id": "android-versions@1.4.0",
"_inBundle": true,
"_integrity": "sha512-GnomfYsBq+nZh3c3UH/4r9Jt6FuTxdhUJbeHIdYOH5xBhQ8I0ZzC2/RM5IFFIjrzuNWSHb8JWP1lPK0/a26jrg==",
"_location": "/cordova-android/android-versions",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "android-versions@1",
"name": "android-versions",
"escapedName": "android-versions",
"rawSpec": "1",
"saveSpec": null,
"fetchSpec": "1"
},
"_requiredBy": [
"/cordova-android"
],
"_resolved": "https://registry.npmjs.org/android-versions/-/android-versions-1.4.0.tgz",
"_shasum": "807ea2941d7e5780e6dd61c5d9b7b6f3c0706e09",
"_spec": "android-versions@1",
"_where": "/Users/brodybits/Documents/cordova/cordova-android",
"author": {
"name": "dvoiss"
},
"bugs": {
"url": "https://github.com/dvoiss/android-versions/issues"
},
"bundleDependencies": false,
"dependencies": {
"semver": "^5.4.1"
},
"deprecated": false,
"description": "Get the name, API level, version level, NDK level, or version code from any version of Android.",
"devDependencies": {
"jshint": "^2.9.2",
"tape": "^4.6.0"
},
"homepage": "https://github.com/dvoiss/android-versions#readme",
"keywords": [
"android",
"version",
"versions",
"ndk",
"nougat",
"marshmallow",
"api",
"level"
],
"license": "MIT",
"main": "index.js",
"name": "android-versions",
"pre-commit": [
"jshint"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dvoiss/android-versions.git"
},
"scripts": {
"jshint": "jshint .",
"test": "tape tests/**/*.js"
},
"version": "1.4.0"
}

View File

@ -1,118 +0,0 @@
"use strict";
const test = require('tape')
const android = require('..')
test('get specific version by API level', (t) => {
t.plan(1)
t.equal(android.get(24).name, "Nougat")
})
test('getAll versions by API level', (t) => {
t.plan(1)
t.equal(android.getAll(24)[0].name, "Nougat")
})
test('get specific version by predicate', (t) => {
t.plan(2)
let actual = android.get((version) => {
return version.name.indexOf("on") !== -1
})
t.equal(actual.name, "Donut")
actual = android.get((version) => {
return version.ndk > 5 && version.api < 15
})
t.equal(actual.versionCode, "HONEYCOMB_MR1")
})
test('getAll versions by predicate', (t) => {
t.plan(3)
let actual = android.getAll((version) => {
return version.name.indexOf("on") !== -1
}).map((version) => version.name)
t.deepEqual(actual, ["Donut", "Honeycomb", "Honeycomb", "Honeycomb"])
actual = android.getAll((version) => {
return version.ndk > 5 && version.api < 15
}).map((version) => version.versionCode)
t.deepEqual(actual, ["HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH"])
actual = android.getAll((version) => {
return version.api > 22
}).map((version) => version.versionCode)
t.deepEqual(actual, ["M", "N", "N_MR1", "O", "O_MR1", "P"])
})
test('get version by semantic version', (t) => {
t.plan(4)
t.equal(android.get("6.0").versionCode, android.M.versionCode)
t.equal(android.get("6.0.0").versionCode, android.M.versionCode)
t.equal(android.get("2.3").versionCode, android.GINGERBREAD.versionCode)
t.equal(android.get("2.3.3").versionCode, android.GINGERBREAD_MR1.versionCode)
})
test('support major version only', (t) => {
t.plan(2)
t.equal(android.get("9.0").versionCode, android.P.versionCode)
t.equal(android.get("9.0.0").versionCode, android.P.versionCode)
})
test('support version ranges', (t) => {
t.plan(7)
let tests = [ "4.4", "4.4.0", "4.4.1", "4.4.2", "4.4.3", "4.4.4" ]
tests.forEach((versionCode) => {
t.equal(android.get(versionCode).versionCode, android.KITKAT.versionCode)
})
t.equal(android.get("4.4.5"), null)
})
test('support x-ranges', (t) => {
t.plan(12)
let tests = [
"4.1", "4.1.0", "4.1.1", "4.1.2", "4.1.3", "4.1.4",
"4.1.5", "4.1.6", "4.1.7", "4.1.8", "4.1.9", "4.1.10"
]
tests.forEach((versionCode) => {
t.equal(android.get(versionCode).versionCode, android.JELLY_BEAN.versionCode)
})
})
test('access version codes object', (t) => {
t.plan(1)
t.ok(android.VERSIONS)
})
test('access specific versions directly', (t) => {
t.plan(28)
t.ok(android.BASE)
t.ok(android.BASE_1_1)
t.ok(android.CUPCAKE)
t.ok(android.DONUT)
t.ok(android.ECLAIR)
t.ok(android.ECLAIR_0_1)
t.ok(android.ECLAIR_MR1)
t.ok(android.FROYO)
t.ok(android.GINGERBREAD)
t.ok(android.GINGERBREAD_MR1)
t.ok(android.HONEYCOMB)
t.ok(android.HONEYCOMB_MR1)
t.ok(android.HONEYCOMB_MR2)
t.ok(android.ICE_CREAM_SANDWICH)
t.ok(android.ICE_CREAM_SANDWICH_MR1)
t.ok(android.JELLY_BEAN)
t.ok(android.JELLY_BEAN_MR1)
t.ok(android.JELLY_BEAN_MR2)
t.ok(android.KITKAT)
t.ok(android.KITKAT_WATCH)
t.ok(android.LOLLIPOP)
t.ok(android.LOLLIPOP_MR1)
t.ok(android.M)
t.ok(android.N)
t.ok(android.N_MR1)
t.ok(android.O)
t.ok(android.O_MR1)
t.ok(android.P)
})

View File

@ -1,4 +0,0 @@
{
"laxcomma": true,
"asi": true
}

View File

@ -1 +0,0 @@
node_modules

View File

@ -1,23 +0,0 @@
0.3.1 / 2016-01-14
==================
* add MIT LICENSE file (#23, @kasicka)
* preserve chaining after redundant style-method calls (#19, @drewblaisdell)
* package: add "license" field (#16, @BenjaminTsai)
0.3.0 / 2014-05-09
==================
* package: remove "test" script and "devDependencies"
* package: remove "engines" section
* pacakge: remove "bin" section
* package: beautify
* examples: remove `starwars` example (#15)
* Documented goto, horizontalAbsolute, and eraseLine methods in README.md (#12, @Jammerwoch)
* add `.jshintrc` file
< 0.3.0
=======
* Prehistoric

View File

@ -1,24 +0,0 @@
(The MIT License)
Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,98 +0,0 @@
ansi.js
=========
### Advanced ANSI formatting tool for Node.js
`ansi.js` is a module for Node.js that provides an easy-to-use API for
writing ANSI escape codes to `Stream` instances. ANSI escape codes are used to do
fancy things in a terminal window, like render text in colors, delete characters,
lines, the entire window, or hide and show the cursor, and lots more!
#### Features:
* 256 color support for the terminal!
* Make a beep sound from your terminal!
* Works with *any* writable `Stream` instance.
* Allows you to move the cursor anywhere on the terminal window.
* Allows you to delete existing contents from the terminal window.
* Allows you to hide and show the cursor.
* Converts CSS color codes and RGB values into ANSI escape codes.
* Low-level; you are in control of when escape codes are used, it's not abstracted.
Installation
------------
Install with `npm`:
``` bash
$ npm install ansi
```
Example
-------
``` js
var ansi = require('ansi')
, cursor = ansi(process.stdout)
// You can chain your calls forever:
cursor
.red() // Set font color to red
.bg.grey() // Set background color to grey
.write('Hello World!') // Write 'Hello World!' to stdout
.bg.reset() // Reset the bgcolor before writing the trailing \n,
// to avoid Terminal glitches
.write('\n') // And a final \n to wrap things up
// Rendering modes are persistent:
cursor.hex('#660000').bold().underline()
// You can use the regular logging functions, text will be green:
console.log('This is blood red, bold text')
// To reset just the foreground color:
cursor.fg.reset()
console.log('This will still be bold')
// to go to a location (x,y) on the console
// note: 1-indexed, not 0-indexed:
cursor.goto(10, 5).write('Five down, ten over')
// to clear the current line:
cursor.horizontalAbsolute(0).eraseLine().write('Starting again')
// to go to a different column on the current line:
cursor.horizontalAbsolute(5).write('column five')
// Clean up after yourself!
cursor.reset()
```
License
-------
(The MIT License)
Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,16 +0,0 @@
#!/usr/bin/env node
/**
* Invokes the terminal "beep" sound once per second on every exact second.
*/
process.title = 'beep'
var cursor = require('../../')(process.stdout)
function beep () {
cursor.beep()
setTimeout(beep, 1000 - (new Date()).getMilliseconds())
}
setTimeout(beep, 1000 - (new Date()).getMilliseconds())

View File

@ -1,15 +0,0 @@
#!/usr/bin/env node
/**
* Like GNU ncurses "clear" command.
* https://github.com/mscdex/node-ncurses/blob/master/deps/ncurses/progs/clear.c
*/
process.title = 'clear'
function lf () { return '\n' }
require('../../')(process.stdout)
.write(Array.apply(null, Array(process.stdout.getWindowSize()[1])).map(lf).join(''))
.eraseData(2)
.goto(1, 1)

View File

@ -1,32 +0,0 @@
#!/usr/bin/env node
var tty = require('tty')
var cursor = require('../')(process.stdout)
// listen for the queryPosition report on stdin
process.stdin.resume()
raw(true)
process.stdin.once('data', function (b) {
var match = /\[(\d+)\;(\d+)R$/.exec(b.toString())
if (match) {
var xy = match.slice(1, 3).reverse().map(Number)
console.error(xy)
}
// cleanup and close stdin
raw(false)
process.stdin.pause()
})
// send the query position request code to stdout
cursor.queryPosition()
function raw (mode) {
if (process.stdin.setRawMode) {
process.stdin.setRawMode(mode)
} else {
tty.setRawMode(mode)
}
}

View File

@ -1,87 +0,0 @@
#!/usr/bin/env node
var assert = require('assert')
, ansi = require('../../')
function Progress (stream, width) {
this.cursor = ansi(stream)
this.delta = this.cursor.newlines
this.width = width | 0 || 10
this.open = '['
this.close = ']'
this.complete = '█'
this.incomplete = '_'
// initial render
this.progress = 0
}
Object.defineProperty(Progress.prototype, 'progress', {
get: get
, set: set
, configurable: true
, enumerable: true
})
function get () {
return this._progress
}
function set (v) {
this._progress = Math.max(0, Math.min(v, 100))
var w = this.width - this.complete.length - this.incomplete.length
, n = w * (this._progress / 100) | 0
, i = w - n
, com = c(this.complete, n)
, inc = c(this.incomplete, i)
, delta = this.cursor.newlines - this.delta
assert.equal(com.length + inc.length, w)
if (delta > 0) {
this.cursor.up(delta)
this.delta = this.cursor.newlines
}
this.cursor
.horizontalAbsolute(0)
.eraseLine(2)
.fg.white()
.write(this.open)
.fg.grey()
.bold()
.write(com)
.resetBold()
.write(inc)
.fg.white()
.write(this.close)
.fg.reset()
.write('\n')
}
function c (char, length) {
return Array.apply(null, Array(length)).map(function () {
return char
}).join('')
}
// Usage
var width = parseInt(process.argv[2], 10) || process.stdout.getWindowSize()[0] / 2
, p = new Progress(process.stdout, width)
;(function tick () {
p.progress += Math.random() * 5
p.cursor
.eraseLine(2)
.write('Progress: ')
.bold().write(p.progress.toFixed(2))
.write('%')
.resetBold()
.write('\n')
if (p.progress < 100)
setTimeout(tick, 100)
})()

View File

@ -1,405 +0,0 @@
/**
* References:
*
* - http://en.wikipedia.org/wiki/ANSI_escape_code
* - http://www.termsys.demon.co.uk/vtansi.htm
*
*/
/**
* Module dependencies.
*/
var emitNewlineEvents = require('./newlines')
, prefix = '\x1b[' // For all escape codes
, suffix = 'm' // Only for color codes
/**
* The ANSI escape sequences.
*/
var codes = {
up: 'A'
, down: 'B'
, forward: 'C'
, back: 'D'
, nextLine: 'E'
, previousLine: 'F'
, horizontalAbsolute: 'G'
, eraseData: 'J'
, eraseLine: 'K'
, scrollUp: 'S'
, scrollDown: 'T'
, savePosition: 's'
, restorePosition: 'u'
, queryPosition: '6n'
, hide: '?25l'
, show: '?25h'
}
/**
* Rendering ANSI codes.
*/
var styles = {
bold: 1
, italic: 3
, underline: 4
, inverse: 7
}
/**
* The negating ANSI code for the rendering modes.
*/
var reset = {
bold: 22
, italic: 23
, underline: 24
, inverse: 27
}
/**
* The standard, styleable ANSI colors.
*/
var colors = {
white: 37
, black: 30
, blue: 34
, cyan: 36
, green: 32
, magenta: 35
, red: 31
, yellow: 33
, grey: 90
, brightBlack: 90
, brightRed: 91
, brightGreen: 92
, brightYellow: 93
, brightBlue: 94
, brightMagenta: 95
, brightCyan: 96
, brightWhite: 97
}
/**
* Creates a Cursor instance based off the given `writable stream` instance.
*/
function ansi (stream, options) {
if (stream._ansicursor) {
return stream._ansicursor
} else {
return stream._ansicursor = new Cursor(stream, options)
}
}
module.exports = exports = ansi
/**
* The `Cursor` class.
*/
function Cursor (stream, options) {
if (!(this instanceof Cursor)) {
return new Cursor(stream, options)
}
if (typeof stream != 'object' || typeof stream.write != 'function') {
throw new Error('a valid Stream instance must be passed in')
}
// the stream to use
this.stream = stream
// when 'enabled' is false then all the functions are no-ops except for write()
this.enabled = options && options.enabled
if (typeof this.enabled === 'undefined') {
this.enabled = stream.isTTY
}
this.enabled = !!this.enabled
// then `buffering` is true, then `write()` calls are buffered in
// memory until `flush()` is invoked
this.buffering = !!(options && options.buffering)
this._buffer = []
// controls the foreground and background colors
this.fg = this.foreground = new Colorer(this, 0)
this.bg = this.background = new Colorer(this, 10)
// defaults
this.Bold = false
this.Italic = false
this.Underline = false
this.Inverse = false
// keep track of the number of "newlines" that get encountered
this.newlines = 0
emitNewlineEvents(stream)
stream.on('newline', function () {
this.newlines++
}.bind(this))
}
exports.Cursor = Cursor
/**
* Helper function that calls `write()` on the underlying Stream.
* Returns `this` instead of the write() return value to keep
* the chaining going.
*/
Cursor.prototype.write = function (data) {
if (this.buffering) {
this._buffer.push(arguments)
} else {
this.stream.write.apply(this.stream, arguments)
}
return this
}
/**
* Buffer `write()` calls into memory.
*
* @api public
*/
Cursor.prototype.buffer = function () {
this.buffering = true
return this
}
/**
* Write out the in-memory buffer.
*
* @api public
*/
Cursor.prototype.flush = function () {
this.buffering = false
var str = this._buffer.map(function (args) {
if (args.length != 1) throw new Error('unexpected args length! ' + args.length);
return args[0];
}).join('');
this._buffer.splice(0); // empty
this.write(str);
return this
}
/**
* The `Colorer` class manages both the background and foreground colors.
*/
function Colorer (cursor, base) {
this.current = null
this.cursor = cursor
this.base = base
}
exports.Colorer = Colorer
/**
* Write an ANSI color code, ensuring that the same code doesn't get rewritten.
*/
Colorer.prototype._setColorCode = function setColorCode (code) {
var c = String(code)
if (this.current === c) return
this.cursor.enabled && this.cursor.write(prefix + c + suffix)
this.current = c
return this
}
/**
* Set up the positional ANSI codes.
*/
Object.keys(codes).forEach(function (name) {
var code = String(codes[name])
Cursor.prototype[name] = function () {
var c = code
if (arguments.length > 0) {
c = toArray(arguments).map(Math.round).join(';') + code
}
this.enabled && this.write(prefix + c)
return this
}
})
/**
* Set up the functions for the rendering ANSI codes.
*/
Object.keys(styles).forEach(function (style) {
var name = style[0].toUpperCase() + style.substring(1)
, c = styles[style]
, r = reset[style]
Cursor.prototype[style] = function () {
if (this[name]) return this
this.enabled && this.write(prefix + c + suffix)
this[name] = true
return this
}
Cursor.prototype['reset' + name] = function () {
if (!this[name]) return this
this.enabled && this.write(prefix + r + suffix)
this[name] = false
return this
}
})
/**
* Setup the functions for the standard colors.
*/
Object.keys(colors).forEach(function (color) {
var code = colors[color]
Colorer.prototype[color] = function () {
this._setColorCode(this.base + code)
return this.cursor
}
Cursor.prototype[color] = function () {
return this.foreground[color]()
}
})
/**
* Makes a beep sound!
*/
Cursor.prototype.beep = function () {
this.enabled && this.write('\x07')
return this
}
/**
* Moves cursor to specific position
*/
Cursor.prototype.goto = function (x, y) {
x = x | 0
y = y | 0
this.enabled && this.write(prefix + y + ';' + x + 'H')
return this
}
/**
* Resets the color.
*/
Colorer.prototype.reset = function () {
this._setColorCode(this.base + 39)
return this.cursor
}
/**
* Resets all ANSI formatting on the stream.
*/
Cursor.prototype.reset = function () {
this.enabled && this.write(prefix + '0' + suffix)
this.Bold = false
this.Italic = false
this.Underline = false
this.Inverse = false
this.foreground.current = null
this.background.current = null
return this
}
/**
* Sets the foreground color with the given RGB values.
* The closest match out of the 216 colors is picked.
*/
Colorer.prototype.rgb = function (r, g, b) {
var base = this.base + 38
, code = rgb(r, g, b)
this._setColorCode(base + ';5;' + code)
return this.cursor
}
/**
* Same as `cursor.fg.rgb(r, g, b)`.
*/
Cursor.prototype.rgb = function (r, g, b) {
return this.foreground.rgb(r, g, b)
}
/**
* Accepts CSS color codes for use with ANSI escape codes.
* For example: `#FF000` would be bright red.
*/
Colorer.prototype.hex = function (color) {
return this.rgb.apply(this, hex(color))
}
/**
* Same as `cursor.fg.hex(color)`.
*/
Cursor.prototype.hex = function (color) {
return this.foreground.hex(color)
}
// UTIL FUNCTIONS //
/**
* Translates a 255 RGB value to a 0-5 ANSI RGV value,
* then returns the single ANSI color code to use.
*/
function rgb (r, g, b) {
var red = r / 255 * 5
, green = g / 255 * 5
, blue = b / 255 * 5
return rgb5(red, green, blue)
}
/**
* Turns rgb 0-5 values into a single ANSI color code to use.
*/
function rgb5 (r, g, b) {
var red = Math.round(r)
, green = Math.round(g)
, blue = Math.round(b)
return 16 + (red*36) + (green*6) + blue
}
/**
* Accepts a hex CSS color code string (# is optional) and
* translates it into an Array of 3 RGB 0-255 values, which
* can then be used with rgb().
*/
function hex (color) {
var c = color[0] === '#' ? color.substring(1) : color
, r = c.substring(0, 2)
, g = c.substring(2, 4)
, b = c.substring(4, 6)
return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16)]
}
/**
* Turns an array-like object into a real array.
*/
function toArray (a) {
var i = 0
, l = a.length
, rtn = []
for (; i<l; i++) {
rtn.push(a[i])
}
return rtn
}

View File

@ -1,71 +0,0 @@
/**
* Accepts any node Stream instance and hijacks its "write()" function,
* so that it can count any newlines that get written to the output.
*
* When a '\n' byte is encountered, then a "newline" event will be emitted
* on the stream, with no arguments. It is up to the listeners to determine
* any necessary deltas required for their use-case.
*
* Ex:
*
* var cursor = ansi(process.stdout)
* , ln = 0
* process.stdout.on('newline', function () {
* ln++
* })
*/
/**
* Module dependencies.
*/
var assert = require('assert')
var NEWLINE = '\n'.charCodeAt(0)
function emitNewlineEvents (stream) {
if (stream._emittingNewlines) {
// already emitting newline events
return
}
var write = stream.write
stream.write = function (data) {
// first write the data
var rtn = write.apply(stream, arguments)
if (stream.listeners('newline').length > 0) {
var len = data.length
, i = 0
// now try to calculate any deltas
if (typeof data == 'string') {
for (; i<len; i++) {
processByte(stream, data.charCodeAt(i))
}
} else {
// buffer
for (; i<len; i++) {
processByte(stream, data[i])
}
}
}
return rtn
}
stream._emittingNewlines = true
}
module.exports = emitNewlineEvents
/**
* Processes an individual byte being written to a stream
*/
function processByte (stream, b) {
assert.equal(typeof b, 'number')
if (b === NEWLINE) {
stream.emit('newline')
}
}

View File

@ -1,56 +0,0 @@
{
"_from": "ansi@^0.3.1",
"_id": "ansi@0.3.1",
"_inBundle": true,
"_integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=",
"_location": "/cordova-android/ansi",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ansi@^0.3.1",
"name": "ansi",
"escapedName": "ansi",
"rawSpec": "^0.3.1",
"saveSpec": null,
"fetchSpec": "^0.3.1"
},
"_requiredBy": [
"/cordova-android",
"/cordova-android/cordova-common"
],
"_resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz",
"_shasum": "0c42d4fb17160d5a9af1e484bace1c66922c1b21",
"_spec": "ansi@^0.3.1",
"_where": "/Users/brodybits/Documents/cordova/cordova-android/node_modules/cordova-common",
"author": {
"name": "Nathan Rajlich",
"email": "nathan@tootallnate.net",
"url": "http://tootallnate.net"
},
"bugs": {
"url": "https://github.com/TooTallNate/ansi.js/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Advanced ANSI formatting tool for Node.js",
"homepage": "https://github.com/TooTallNate/ansi.js#readme",
"keywords": [
"ansi",
"formatting",
"cursor",
"color",
"terminal",
"rgb",
"256",
"stream"
],
"license": "MIT",
"main": "./lib/ansi.js",
"name": "ansi",
"repository": {
"type": "git",
"url": "git://github.com/TooTallNate/ansi.js.git"
},
"version": "0.3.1"
}

View File

@ -1,5 +0,0 @@
test
.gitignore
.travis.yml
Makefile
example.js

View File

@ -1,21 +0,0 @@
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,91 +0,0 @@
# balanced-match
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well!
[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match)
[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match)
[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match)
## Example
Get the first matching pair of braces:
```js
var balanced = require('balanced-match');
console.log(balanced('{', '}', 'pre{in{nested}}post'));
console.log(balanced('{', '}', 'pre{first}between{second}post'));
console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'));
```
The matches are:
```bash
$ node example.js
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
{ start: 3,
end: 9,
pre: 'pre',
body: 'first',
post: 'between{second}post' }
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
```
## API
### var m = balanced(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
object with those keys:
* **start** the index of the first match of `a`
* **end** the index of the matching `b`
* **pre** the preamble, `a` and `b` not included
* **body** the match, `a` and `b` not included
* **post** the postscript, `a` and `b` not included
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
### var r = balanced.range(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
array with indexes: `[ <a index>, <b index> ]`.
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install balanced-match
```
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,59 +0,0 @@
'use strict';
module.exports = balanced;
function balanced(a, b, str) {
if (a instanceof RegExp) a = maybeMatch(a, str);
if (b instanceof RegExp) b = maybeMatch(b, str);
var r = range(a, b, str);
return r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + a.length, r[1]),
post: str.slice(r[1] + b.length)
};
}
function maybeMatch(reg, str) {
var m = str.match(reg);
return m ? m[0] : null;
}
balanced.range = range;
function range(a, b, str) {
var begs, beg, left, right, result;
var ai = str.indexOf(a);
var bi = str.indexOf(b, ai + 1);
var i = ai;
if (ai >= 0 && bi > 0) {
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i == ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
} else if (begs.length == 1) {
result = [ begs.pop(), bi ];
} else {
beg = begs.pop();
if (beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length) {
result = [ left, right ];
}
}
return result;
}

View File

@ -1,78 +0,0 @@
{
"_from": "balanced-match@^1.0.0",
"_id": "balanced-match@1.0.0",
"_inBundle": true,
"_integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"_location": "/cordova-android/balanced-match",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "balanced-match@^1.0.0",
"name": "balanced-match",
"escapedName": "balanced-match",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/cordova-android",
"/cordova-android/brace-expansion"
],
"_resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"_shasum": "89b4d199ab2bee49de164ea02b89ce462d71b767",
"_spec": "balanced-match@^1.0.0",
"_where": "/Users/brodybits/Documents/cordova/cordova-android/node_modules/brace-expansion",
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"bugs": {
"url": "https://github.com/juliangruber/balanced-match/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"homepage": "https://github.com/juliangruber/balanced-match",
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"license": "MIT",
"main": "index.js",
"name": "balanced-match",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"scripts": {
"bench": "make bench",
"test": "make test"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"version": "1.0.0"
}

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,32 +0,0 @@
base64-js
=========
`base64-js` does basic base64 encoding/decoding in pure JS.
[![build status](https://secure.travis-ci.org/beatgammit/base64-js.png)](http://travis-ci.org/beatgammit/base64-js)
[![testling badge](https://ci.testling.com/beatgammit/base64-js.png)](https://ci.testling.com/beatgammit/base64-js)
Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data.
Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does.
## install
With [npm](https://npmjs.org) do:
`npm install base64-js`
## methods
`var base64 = require('base64-js')`
`base64` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument.
* `byteLength` - Takes a base64 string and returns length of byte array
* `toByteArray` - Takes a base64 string and returns a byte array
* `fromByteArray` - Takes a byte array and returns a base64 string
## license
MIT

View File

@ -1 +0,0 @@
(function(r){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=r()}else if(typeof define==="function"&&define.amd){define([],r)}else{var e;if(typeof window!=="undefined"){e=window}else if(typeof global!=="undefined"){e=global}else if(typeof self!=="undefined"){e=self}else{e=this}e.base64js=r()}})(function(){var r,e,t;return function r(e,t,n){function o(i,a){if(!t[i]){if(!e[i]){var u=typeof require=="function"&&require;if(!a&&u)return u(i,!0);if(f)return f(i,!0);var d=new Error("Cannot find module '"+i+"'");throw d.code="MODULE_NOT_FOUND",d}var c=t[i]={exports:{}};e[i][0].call(c.exports,function(r){var t=e[i][1][r];return o(t?t:r)},c,c.exports,r,e,t,n)}return t[i].exports}var f=typeof require=="function"&&require;for(var i=0;i<n.length;i++)o(n[i]);return o}({"/":[function(r,e,t){"use strict";t.byteLength=c;t.toByteArray=v;t.fromByteArray=s;var n=[];var o=[];var f=typeof Uint8Array!=="undefined"?Uint8Array:Array;var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(var a=0,u=i.length;a<u;++a){n[a]=i[a];o[i.charCodeAt(a)]=a}o["-".charCodeAt(0)]=62;o["_".charCodeAt(0)]=63;function d(r){var e=r.length;if(e%4>0){throw new Error("Invalid string. Length must be a multiple of 4")}return r[e-2]==="="?2:r[e-1]==="="?1:0}function c(r){return r.length*3/4-d(r)}function v(r){var e,t,n,i,a,u;var c=r.length;a=d(r);u=new f(c*3/4-a);n=a>0?c-4:c;var v=0;for(e=0,t=0;e<n;e+=4,t+=3){i=o[r.charCodeAt(e)]<<18|o[r.charCodeAt(e+1)]<<12|o[r.charCodeAt(e+2)]<<6|o[r.charCodeAt(e+3)];u[v++]=i>>16&255;u[v++]=i>>8&255;u[v++]=i&255}if(a===2){i=o[r.charCodeAt(e)]<<2|o[r.charCodeAt(e+1)]>>4;u[v++]=i&255}else if(a===1){i=o[r.charCodeAt(e)]<<10|o[r.charCodeAt(e+1)]<<4|o[r.charCodeAt(e+2)]>>2;u[v++]=i>>8&255;u[v++]=i&255}return u}function l(r){return n[r>>18&63]+n[r>>12&63]+n[r>>6&63]+n[r&63]}function h(r,e,t){var n;var o=[];for(var f=e;f<t;f+=3){n=(r[f]<<16)+(r[f+1]<<8)+r[f+2];o.push(l(n))}return o.join("")}function s(r){var e;var t=r.length;var o=t%3;var f="";var i=[];var a=16383;for(var u=0,d=t-o;u<d;u+=a){i.push(h(r,u,u+a>d?d:u+a))}if(o===1){e=r[t-1];f+=n[e>>2];f+=n[e<<4&63];f+="=="}else if(o===2){e=(r[t-2]<<8)+r[t-1];f+=n[e>>10];f+=n[e>>4&63];f+=n[e<<2&63];f+="="}i.push(f);return i.join("")}},{}]},{},[])("/")});

Some files were not shown because too many files have changed in this diff Show More