From c56cd4d5a8fdf2fc80ee8a9f1c960f21fca87a9a Mon Sep 17 00:00:00 2001 From: Sukant Pal Date: Sat, 1 Feb 2020 03:34:51 -0500 Subject: [PATCH] refactor: use es6 class (#911) Refactored to Classes: * Api * AndroidManifest * AndroidProject --- bin/templates/cordova/Api.js | 595 ++++++++++--------- bin/templates/cordova/lib/AndroidManifest.js | 196 +++--- bin/templates/cordova/lib/AndroidProject.js | 284 ++++----- 3 files changed, 540 insertions(+), 535 deletions(-) diff --git a/bin/templates/cordova/Api.js b/bin/templates/cordova/Api.js index 83f78277..e6402fe3 100644 --- a/bin/templates/cordova/Api.js +++ b/bin/templates/cordova/Api.js @@ -51,317 +51,320 @@ function setupEvents (externalEventEmitter) { * The PlatformApi instance also should define the following field: * * * platform: String that defines a platform name. + * @class Api */ -function Api (platform, platformRootDir, events) { - this.platform = PLATFORM; - this.root = path.resolve(__dirname, '..'); +class Api { + constructor (platform, platformRootDir, events) { + this.platform = PLATFORM; + this.root = path.resolve(__dirname, '..'); - setupEvents(events); + setupEvents(events); - const appMain = path.join(this.root, 'app', 'src', 'main'); - const appRes = path.join(appMain, 'res'); + const appMain = path.join(this.root, 'app', 'src', 'main'); + const appRes = path.join(appMain, 'res'); - this.locations = { - root: this.root, - www: path.join(appMain, 'assets', 'www'), - res: appRes, - platformWww: path.join(this.root, 'platform_www'), - configXml: path.join(appRes, 'xml', 'config.xml'), - defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'), - strings: path.join(appRes, 'values', 'strings.xml'), - manifest: path.join(appMain, 'AndroidManifest.xml'), - build: path.join(this.root, 'build'), - javaSrc: path.join(appMain, 'java') - }; -} - -/** - * Installs platform to specified directory and creates a platform project. - * - * @param {String} destination Destination directory, where insatll platform to - * @param {ConfigParser} [config] ConfgiParser instance, used to retrieve - * project creation options, such as package id and project name. - * @param {Object} [options] An options object. The most common options are: - * @param {String} [options.customTemplate] A path to custom template, that - * should override the default one from platform. - * @param {Boolean} [options.link] Flag that indicates that platform's - * sources will be linked to installed platform instead of copying. - * @param {EventEmitter} [events] An EventEmitter instance that will be used for - * logging purposes. If no EventEmitter provided, all events will be logged to - * console - * - * @return {Promise} Promise either fulfilled with PlatformApi - * instance or rejected with CordovaError. - */ -Api.createPlatform = function (destination, config, options, events) { - events = setupEvents(events); - var result; - try { - result = require('../../lib/create').create(destination, config, options, events).then(function (destination) { - return new Api(PLATFORM, destination, events); - }); - } catch (e) { - events.emit('error', 'createPlatform is not callable from the android project API.'); - throw (e); - } - return result; -}; - -/** - * Updates already installed platform. - * - * @param {String} destination Destination directory, where platform installed - * @param {Object} [options] An options object. The most common options are: - * @param {String} [options.customTemplate] A path to custom template, that - * should override the default one from platform. - * @param {Boolean} [options.link] Flag that indicates that platform's - * sources will be linked to installed platform instead of copying. - * @param {EventEmitter} [events] An EventEmitter instance that will be used for - * logging purposes. If no EventEmitter provided, all events will be logged to - * console - * - * @return {Promise} Promise either fulfilled with PlatformApi - * instance or rejected with CordovaError. - */ -Api.updatePlatform = function (destination, options, events) { - events = setupEvents(events); - var result; - try { - result = require('../../lib/create').update(destination, options, events).then(function (destination) { - return new Api(PLATFORM, destination, events); - }); - } catch (e) { - events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.'); - throw (e); - } - return result; -}; - -/** - * Gets a CordovaPlatform object, that represents the platform structure. - * - * @return {CordovaPlatform} A structure that contains the description of - * platform's file structure and other properties of platform. - */ -Api.prototype.getPlatformInfo = function () { - var result = {}; - result.locations = this.locations; - result.root = this.root; - result.name = this.platform; - result.version = require('./version'); - result.projectConfig = this._config; - - return result; -}; - -/** - * Updates installed platform with provided www assets and new app - * configuration. This method is required for CLI workflow and will be called - * each time before build, so the changes, made to app configuration and www - * code, will be applied to platform. - * - * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a - * project structure and configuration, that should be applied to platform - * (contains project's www location and ConfigParser instance for project's - * config). - * - * @return {Promise} Return a promise either fulfilled, or rejected with - * CordovaError instance. - */ -Api.prototype.prepare = function (cordovaProject, prepareOptions) { - cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path); - - return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions); -}; - -/** - * Installs a new plugin into platform. This method only copies non-www files - * (sources, libs, etc.) to platform. It also doesn't resolves the - * dependencies of plugin. Both of handling of www files, such as assets and - * js-files and resolving dependencies are the responsibility of caller. - * - * @param {PluginInfo} plugin A PluginInfo instance that represents plugin - * that will be installed. - * @param {Object} installOptions An options object. Possible options below: - * @param {Boolean} installOptions.link: Flag that specifies that plugin - * sources will be symlinked to app's directory instead of copying (if - * possible). - * @param {Object} installOptions.variables An object that represents - * variables that will be used to install plugin. See more details on plugin - * variables in documentation: - * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html - * - * @return {Promise} Return a promise either fulfilled, or rejected with - * CordovaError instance. - */ -Api.prototype.addPlugin = function (plugin, installOptions) { - var project = AndroidProject.getProjectFile(this.root); - var self = this; - - installOptions = installOptions || {}; - installOptions.variables = installOptions.variables || {}; - // Add PACKAGE_NAME variable into vars - if (!installOptions.variables.PACKAGE_NAME) { - installOptions.variables.PACKAGE_NAME = project.getPackageName(); + this.locations = { + root: this.root, + www: path.join(appMain, 'assets', 'www'), + res: appRes, + platformWww: path.join(this.root, 'platform_www'), + configXml: path.join(appRes, 'xml', 'config.xml'), + defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'), + strings: path.join(appRes, 'values', 'strings.xml'), + manifest: path.join(appMain, 'AndroidManifest.xml'), + build: path.join(this.root, 'build'), + javaSrc: path.join(appMain, 'java') + }; } - return Promise.resolve().then(function () { - return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions); - }).then(function () { - if (plugin.getFrameworks(this.platform).length === 0) return; - selfEvents.emit('verbose', 'Updating build files since android plugin contained '); - // This should pick the correct builder, not just get gradle - require('./lib/builders/builders').getBuilder().prepBuildFiles(); - }.bind(this)) - // CB-11022 Return truthy value to prevent running prepare after - .then(() => true); -}; + /** + * Gets a CordovaPlatform object, that represents the platform structure. + * + * @return {CordovaPlatform} A structure that contains the description of + * platform's file structure and other properties of platform. + */ + getPlatformInfo () { + var result = {}; + result.locations = this.locations; + result.root = this.root; + result.name = this.platform; + result.version = require('./version'); + result.projectConfig = this._config; -/** - * Removes an installed plugin from platform. - * - * Since method accepts PluginInfo instance as input parameter instead of plugin - * id, caller shoud take care of managing/storing PluginInfo instances for - * future uninstalls. - * - * @param {PluginInfo} plugin A PluginInfo instance that represents plugin - * that will be installed. - * - * @return {Promise} Return a promise either fulfilled, or rejected with - * CordovaError instance. - */ -Api.prototype.removePlugin = function (plugin, uninstallOptions) { - var project = AndroidProject.getProjectFile(this.root); - - if (uninstallOptions && uninstallOptions.usePlatformWww === true) { - uninstallOptions.usePlatformWww = false; + return result; } - return PluginManager.get(this.platform, this.locations, project) - .removePlugin(plugin, uninstallOptions) - .then(function () { + /** + * Updates installed platform with provided www assets and new app + * configuration. This method is required for CLI workflow and will be called + * each time before build, so the changes, made to app configuration and www + * code, will be applied to platform. + * + * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a + * project structure and configuration, that should be applied to platform + * (contains project's www location and ConfigParser instance for project's + * config). + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ + prepare (cordovaProject, prepareOptions) { + cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path); + + return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions); + } + + /** + * Installs a new plugin into platform. This method only copies non-www files + * (sources, libs, etc.) to platform. It also doesn't resolves the + * dependencies of plugin. Both of handling of www files, such as assets and + * js-files and resolving dependencies are the responsibility of caller. + * + * @param {PluginInfo} plugin A PluginInfo instance that represents plugin + * that will be installed. + * @param {Object} installOptions An options object. Possible options below: + * @param {Boolean} installOptions.link: Flag that specifies that plugin + * sources will be symlinked to app's directory instead of copying (if + * possible). + * @param {Object} installOptions.variables An object that represents + * variables that will be used to install plugin. See more details on plugin + * variables in documentation: + * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ + addPlugin (plugin, installOptions) { + var project = AndroidProject.getProjectFile(this.root); + var self = this; + + installOptions = installOptions || {}; + installOptions.variables = installOptions.variables || {}; + // Add PACKAGE_NAME variable into vars + if (!installOptions.variables.PACKAGE_NAME) { + installOptions.variables.PACKAGE_NAME = project.getPackageName(); + } + + return Promise.resolve().then(function () { + return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions); + }).then(function () { if (plugin.getFrameworks(this.platform).length === 0) return; - selfEvents.emit('verbose', 'Updating build files since android plugin contained '); + // This should pick the correct builder, not just get gradle require('./lib/builders/builders').getBuilder().prepBuildFiles(); }.bind(this)) - // CB-11022 Return truthy value to prevent running prepare after - .then(() => true); -}; - -/** - * Builds an application package for current platform. - * - * @param {Object} buildOptions A build options. This object's structure is - * highly depends on platform's specific. The most common options are: - * @param {Boolean} buildOptions.debug Indicates that packages should be - * built with debug configuration. This is set to true by default unless the - * 'release' option is not specified. - * @param {Boolean} buildOptions.release Indicates that packages should be - * built with release configuration. If not set to true, debug configuration - * will be used. - * @param {Boolean} buildOptions.device Specifies that built app is intended - * to run on device - * @param {Boolean} buildOptions.emulator: Specifies that built app is - * intended to run on emulator - * @param {String} buildOptions.target Specifies the device id that will be - * used to run built application. - * @param {Boolean} buildOptions.nobuild Indicates that this should be a - * dry-run call, so no build artifacts will be produced. - * @param {String[]} buildOptions.archs Specifies chip architectures which - * app packages should be built for. List of valid architectures is depends on - * platform. - * @param {String} buildOptions.buildConfig The path to build configuration - * file. The format of this file is depends on platform. - * @param {String[]} buildOptions.argv Raw array of command-line arguments, - * passed to `build` command. The purpose of this property is to pass a - * platform-specific arguments, and eventually let platform define own - * arguments processing logic. - * - * @return {Promise} A promise either fulfilled with an array of build - * artifacts (application packages) if package was built successfully, - * or rejected with CordovaError. The resultant build artifact objects is not - * strictly typed and may conatin arbitrary set of fields as in sample below. - * - * { - * architecture: 'x86', - * buildType: 'debug', - * path: '/path/to/build', - * type: 'app' - * } - * - * The return value in most cases will contain only one item but in some cases - * there could be multiple items in output array, e.g. when multiple - * arhcitectures is specified. - */ -Api.prototype.build = function (buildOptions) { - var self = this; - - return require('./lib/check_reqs').run().then(function () { - return require('./lib/build').run.call(self, buildOptions); - }).then(function (buildResults) { - // Cast build result to array of build artifacts - return buildResults.paths.map(function (apkPath) { - return { - buildType: buildResults.buildType, - buildMethod: buildResults.buildMethod, - path: apkPath, - type: path.extname(apkPath).replace(/\./g, '') - }; - }); - }); -}; - -/** - * Builds an application package for current platform and runs it on - * specified/default device. If no 'device'/'emulator'/'target' options are - * specified, then tries to run app on default device if connected, otherwise - * runs the app on emulator. - * - * @param {Object} runOptions An options object. The structure is the same - * as for build options. - * - * @return {Promise} A promise either fulfilled if package was built and ran - * successfully, or rejected with CordovaError. - */ -Api.prototype.run = function (runOptions) { - var self = this; - return require('./lib/check_reqs').run().then(function () { - return require('./lib/run').run.call(self, runOptions); - }); -}; - -/** - * Cleans out the build artifacts from platform's directory, and also - * cleans out the platform www directory if called without options specified. - * - * @return {Promise} Return a promise either fulfilled, or rejected with - * CordovaError. - */ -Api.prototype.clean = function (cleanOptions) { - var self = this; - // This will lint, checking for null won't - if (typeof cleanOptions === 'undefined') { - cleanOptions = {}; + // CB-11022 Return truthy value to prevent running prepare after + .then(() => true); } - return require('./lib/check_reqs').run().then(function () { - return require('./lib/build').runClean.call(self, cleanOptions); - }).then(function () { - return require('./lib/prepare').clean.call(self, cleanOptions); - }); -}; + /** + * Removes an installed plugin from platform. + * + * Since method accepts PluginInfo instance as input parameter instead of plugin + * id, caller shoud take care of managing/storing PluginInfo instances for + * future uninstalls. + * + * @param {PluginInfo} plugin A PluginInfo instance that represents plugin + * that will be installed. + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ + removePlugin (plugin, uninstallOptions) { + var project = AndroidProject.getProjectFile(this.root); -/** - * Performs a requirements check for current platform. Each platform defines its - * own set of requirements, which should be resolved before platform can be - * built successfully. - * - * @return {Promise} Promise, resolved with set of Requirement - * objects for current platform. - */ -Api.prototype.requirements = function () { - return require('./lib/check_reqs').check_all(); -}; + if (uninstallOptions && uninstallOptions.usePlatformWww === true) { + uninstallOptions.usePlatformWww = false; + } + + return PluginManager.get(this.platform, this.locations, project) + .removePlugin(plugin, uninstallOptions) + .then(function () { + if (plugin.getFrameworks(this.platform).length === 0) return; + + selfEvents.emit('verbose', 'Updating build files since android plugin contained '); + require('./lib/builders/builders').getBuilder().prepBuildFiles(); + }.bind(this)) + // CB-11022 Return truthy value to prevent running prepare after + .then(() => true); + } + + /** + * Builds an application package for current platform. + * + * @param {Object} buildOptions A build options. This object's structure is + * highly depends on platform's specific. The most common options are: + * @param {Boolean} buildOptions.debug Indicates that packages should be + * built with debug configuration. This is set to true by default unless the + * 'release' option is not specified. + * @param {Boolean} buildOptions.release Indicates that packages should be + * built with release configuration. If not set to true, debug configuration + * will be used. + * @param {Boolean} buildOptions.device Specifies that built app is intended + * to run on device + * @param {Boolean} buildOptions.emulator: Specifies that built app is + * intended to run on emulator + * @param {String} buildOptions.target Specifies the device id that will be + * used to run built application. + * @param {Boolean} buildOptions.nobuild Indicates that this should be a + * dry-run call, so no build artifacts will be produced. + * @param {String[]} buildOptions.archs Specifies chip architectures which + * app packages should be built for. List of valid architectures is depends on + * platform. + * @param {String} buildOptions.buildConfig The path to build configuration + * file. The format of this file is depends on platform. + * @param {String[]} buildOptions.argv Raw array of command-line arguments, + * passed to `build` command. The purpose of this property is to pass a + * platform-specific arguments, and eventually let platform define own + * arguments processing logic. + * + * @return {Promise} A promise either fulfilled with an array of build + * artifacts (application packages) if package was built successfully, + * or rejected with CordovaError. The resultant build artifact objects is not + * strictly typed and may conatin arbitrary set of fields as in sample below. + * + * { + * architecture: 'x86', + * buildType: 'debug', + * path: '/path/to/build', + * type: 'app' + * } + * + * The return value in most cases will contain only one item but in some cases + * there could be multiple items in output array, e.g. when multiple + * arhcitectures is specified. + */ + build (buildOptions) { + var self = this; + + return require('./lib/check_reqs').run().then(function () { + return require('./lib/build').run.call(self, buildOptions); + }).then(function (buildResults) { + // Cast build result to array of build artifacts + return buildResults.paths.map(function (apkPath) { + return { + buildType: buildResults.buildType, + buildMethod: buildResults.buildMethod, + path: apkPath, + type: path.extname(apkPath).replace(/\./g, '') + }; + }); + }); + } + + /** + * Builds an application package for current platform and runs it on + * specified/default device. If no 'device'/'emulator'/'target' options are + * specified, then tries to run app on default device if connected, otherwise + * runs the app on emulator. + * + * @param {Object} runOptions An options object. The structure is the same + * as for build options. + * + * @return {Promise} A promise either fulfilled if package was built and ran + * successfully, or rejected with CordovaError. + */ + run (runOptions) { + var self = this; + return require('./lib/check_reqs').run().then(function () { + return require('./lib/run').run.call(self, runOptions); + }); + } + + /** + * Cleans out the build artifacts from platform's directory, and also + * cleans out the platform www directory if called without options specified. + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError. + */ + clean (cleanOptions) { + var self = this; + // This will lint, checking for null won't + if (typeof cleanOptions === 'undefined') { + cleanOptions = {}; + } + + return require('./lib/check_reqs').run().then(function () { + return require('./lib/build').runClean.call(self, cleanOptions); + }).then(function () { + return require('./lib/prepare').clean.call(self, cleanOptions); + }); + } + + /** + * Performs a requirements check for current platform. Each platform defines its + * own set of requirements, which should be resolved before platform can be + * built successfully. + * + * @return {Promise} Promise, resolved with set of Requirement + * objects for current platform. + */ + requirements () { + return require('./lib/check_reqs').check_all(); + } + + /** + * Installs platform to specified directory and creates a platform project. + * + * @param {String} destination Destination directory, where insatll platform to + * @param {ConfigParser} [config] ConfgiParser instance, used to retrieve + * project creation options, such as package id and project name. + * @param {Object} [options] An options object. The most common options are: + * @param {String} [options.customTemplate] A path to custom template, that + * should override the default one from platform. + * @param {Boolean} [options.link] Flag that indicates that platform's + * sources will be linked to installed platform instead of copying. + * @param {EventEmitter} [events] An EventEmitter instance that will be used for + * logging purposes. If no EventEmitter provided, all events will be logged to + * console + * + * @return {Promise} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ + static createPlatform (destination, config, options, events) { + events = setupEvents(events); + var result; + try { + result = require('../../lib/create').create(destination, config, options, events).then(function (destination) { + return new Api(PLATFORM, destination, events); + }); + } catch (e) { + events.emit('error', 'createPlatform is not callable from the android project API.'); + throw (e); + } + return result; + } + + /** + * Updates already installed platform. + * + * @param {String} destination Destination directory, where platform installed + * @param {Object} [options] An options object. The most common options are: + * @param {String} [options.customTemplate] A path to custom template, that + * should override the default one from platform. + * @param {Boolean} [options.link] Flag that indicates that platform's + * sources will be linked to installed platform instead of copying. + * @param {EventEmitter} [events] An EventEmitter instance that will be used for + * logging purposes. If no EventEmitter provided, all events will be logged to + * console + * + * @return {Promise} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ + static updatePlatform (destination, options, events) { + events = setupEvents(events); + var result; + try { + result = require('../../lib/create').update(destination, options, events).then(function (destination) { + return new Api(PLATFORM, destination, events); + }); + } catch (e) { + events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.'); + throw (e); + } + return result; + } +} module.exports = Api; diff --git a/bin/templates/cordova/lib/AndroidManifest.js b/bin/templates/cordova/lib/AndroidManifest.js index a4489f1f..5d71ed1f 100644 --- a/bin/templates/cordova/lib/AndroidManifest.js +++ b/bin/templates/cordova/lib/AndroidManifest.js @@ -23,104 +23,106 @@ var xml = require('cordova-common').xmlHelpers; var DEFAULT_ORIENTATION = 'default'; /** Wraps an AndroidManifest file */ -function AndroidManifest (path) { - this.path = path; - this.doc = xml.parseElementtreeSync(path); - if (this.doc.getroot().tag !== 'manifest') { - throw new Error('AndroidManifest at ' + path + ' has incorrect root node name (expected "manifest")'); +class AndroidManifest { + constructor (path) { + this.path = path; + this.doc = xml.parseElementtreeSync(path); + if (this.doc.getroot().tag !== 'manifest') { + throw new Error('AndroidManifest at ' + path + ' has incorrect root node name (expected "manifest")'); + } + } + + getVersionName () { + return this.doc.getroot().attrib['android:versionName']; + } + + setVersionName (versionName) { + this.doc.getroot().attrib['android:versionName'] = versionName; + return this; + } + + getVersionCode () { + return this.doc.getroot().attrib['android:versionCode']; + } + + setVersionCode (versionCode) { + this.doc.getroot().attrib['android:versionCode'] = versionCode; + return this; + } + + getPackageId () { + return this.doc.getroot().attrib['package']; + } + + setPackageId (pkgId) { + this.doc.getroot().attrib['package'] = pkgId; + return this; + } + + getActivity () { + var activity = this.doc.getroot().find('./application/activity'); + return { + getName: function () { + return activity.attrib['android:name']; + }, + setName: function (name) { + if (!name) { + delete activity.attrib['android:name']; + } else { + activity.attrib['android:name'] = name; + } + return this; + }, + getOrientation: function () { + return activity.attrib['android:screenOrientation']; + }, + setOrientation: function (orientation) { + if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) { + delete activity.attrib['android:screenOrientation']; + } else { + activity.attrib['android:screenOrientation'] = orientation; + } + return this; + }, + getLaunchMode: function () { + return activity.attrib['android:launchMode']; + }, + setLaunchMode: function (launchMode) { + if (!launchMode) { + delete activity.attrib['android:launchMode']; + } else { + activity.attrib['android:launchMode'] = launchMode; + } + return this; + } + }; + } + + getDebuggable () { + return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true'; + } + + setDebuggable (value) { + var application = this.doc.getroot().find('./application'); + if (value) { + application.attrib['android:debuggable'] = 'true'; + } else { + // The default value is "false", so we can remove attribute at all. + delete application.attrib['android:debuggable']; + } + return this; + } + + /** + * Writes manifest to disk syncronously. If filename is specified, then manifest + * will be written to that file + * + * @param {String} [destPath] File to write manifest to. If omitted, + * manifest will be written to file it has been read from. + */ + write (destPath) { + fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8'); } } -AndroidManifest.prototype.getVersionName = function () { - return this.doc.getroot().attrib['android:versionName']; -}; - -AndroidManifest.prototype.setVersionName = function (versionName) { - this.doc.getroot().attrib['android:versionName'] = versionName; - return this; -}; - -AndroidManifest.prototype.getVersionCode = function () { - return this.doc.getroot().attrib['android:versionCode']; -}; - -AndroidManifest.prototype.setVersionCode = function (versionCode) { - this.doc.getroot().attrib['android:versionCode'] = versionCode; - return this; -}; - -AndroidManifest.prototype.getPackageId = function () { - return this.doc.getroot().attrib['package']; -}; - -AndroidManifest.prototype.setPackageId = function (pkgId) { - this.doc.getroot().attrib['package'] = pkgId; - return this; -}; - -AndroidManifest.prototype.getActivity = function () { - var activity = this.doc.getroot().find('./application/activity'); - return { - getName: function () { - return activity.attrib['android:name']; - }, - setName: function (name) { - if (!name) { - delete activity.attrib['android:name']; - } else { - activity.attrib['android:name'] = name; - } - return this; - }, - getOrientation: function () { - return activity.attrib['android:screenOrientation']; - }, - setOrientation: function (orientation) { - if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) { - delete activity.attrib['android:screenOrientation']; - } else { - activity.attrib['android:screenOrientation'] = orientation; - } - return this; - }, - getLaunchMode: function () { - return activity.attrib['android:launchMode']; - }, - setLaunchMode: function (launchMode) { - if (!launchMode) { - delete activity.attrib['android:launchMode']; - } else { - activity.attrib['android:launchMode'] = launchMode; - } - return this; - } - }; -}; - -AndroidManifest.prototype.getDebuggable = function () { - return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true'; -}; - -AndroidManifest.prototype.setDebuggable = function (value) { - var application = this.doc.getroot().find('./application'); - if (value) { - application.attrib['android:debuggable'] = 'true'; - } else { - // The default value is "false", so we can remove attribute at all. - delete application.attrib['android:debuggable']; - } - return this; -}; - -/** - * Writes manifest to disk syncronously. If filename is specified, then manifest - * will be written to that file - * - * @param {String} [destPath] File to write manifest to. If omitted, - * manifest will be written to file it has been read from. - */ -AndroidManifest.prototype.write = function (destPath) { - fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8'); -}; - module.exports = AndroidManifest; diff --git a/bin/templates/cordova/lib/AndroidProject.js b/bin/templates/cordova/lib/AndroidProject.js index 3c2586a3..5d1c3c32 100644 --- a/bin/templates/cordova/lib/AndroidProject.js +++ b/bin/templates/cordova/lib/AndroidProject.js @@ -55,148 +55,148 @@ function getRelativeLibraryPath (parentDir, subDir) { return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath; } -function AndroidProject (projectDir) { - this._propertiesEditors = {}; - this._subProjectDirs = {}; - this._dirty = false; - this.projectDir = projectDir; - this.platformWww = path.join(this.projectDir, 'platform_www'); - this.www = path.join(this.projectDir, 'app/src/main/assets/www'); +class AndroidProject { + constructor (projectDir) { + this._propertiesEditors = {}; + this._subProjectDirs = {}; + this._dirty = false; + this.projectDir = projectDir; + this.platformWww = path.join(this.projectDir, 'platform_www'); + this.www = path.join(this.projectDir, 'app/src/main/assets/www'); + } + + /** + * Reads the package name out of the Android Manifest file + * + * @param {String} projectDir The absolute path to the directory containing the project + * @return {String} The name of the package + */ + getPackageName () { + var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml'); + return new AndroidManifest(manifestPath).getPackageId(); + } + + getCustomSubprojectRelativeDir (plugin_id, src) { + // All custom subprojects are prefixed with the last portion of the package id. + // This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name. + var packageName = this.getPackageName(); + var lastDotIndex = packageName.lastIndexOf('.'); + var prefix = packageName.substring(lastDotIndex + 1); + var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src)); + return subRelativeDir; + } + + addSubProject (parentDir, subDir) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var subProjectFile = path.resolve(subDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + // TODO: Setting the target needs to happen only for pre-3.7.0 projects + if (fs.existsSync(subProjectFile)) { + var subProperties = this._getPropertiesFile(subProjectFile); + subProperties.set('target', parentProperties.get('target')); + subProperties.dirty = true; + this._subProjectDirs[subDir] = true; + } + addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir)); + + this._dirty = true; + } + + removeSubProject (parentDir, subDir) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir)); + delete this._subProjectDirs[subDir]; + this._dirty = true; + } + + addGradleReference (parentDir, subDir) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir)); + this._dirty = true; + } + + removeGradleReference (parentDir, subDir) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir)); + this._dirty = true; + } + + addSystemLibrary (parentDir, value) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + addToPropertyList(parentProperties, 'cordova.system.library', value); + this._dirty = true; + } + + removeSystemLibrary (parentDir, value) { + var parentProjectFile = path.resolve(parentDir, 'project.properties'); + var parentProperties = this._getPropertiesFile(parentProjectFile); + removeFromPropertyList(parentProperties, 'cordova.system.library', value); + this._dirty = true; + } + + write () { + if (!this._dirty) { + return; + } + this._dirty = false; + + for (var filename in this._propertiesEditors) { + var editor = this._propertiesEditors[filename]; + if (editor.dirty) { + fs.writeFileSync(filename, editor.toString()); + editor.dirty = false; + } + } + } + + getInstaller (type) { + return pluginHandlers.getInstaller(type); + } + + getUninstaller (type) { + return pluginHandlers.getUninstaller(type); + } + + /* + * This checks if an Android project is clean or has old build artifacts + */ + isClean () { + var build_path = path.join(this.projectDir, 'build'); + // If the build directory doesn't exist, it's clean + return !(fs.existsSync(build_path)); + } + + _getPropertiesFile (filename) { + if (!this._propertiesEditors[filename]) { + if (fs.existsSync(filename)) { + this._propertiesEditors[filename] = properties_parser.createEditor(filename); + } else { + this._propertiesEditors[filename] = properties_parser.createEditor(); + } + } + + return this._propertiesEditors[filename]; + } + + static getProjectFile (projectDir) { + if (!projectFileCache[projectDir]) { + projectFileCache[projectDir] = new AndroidProject(projectDir); + } + + return projectFileCache[projectDir]; + } + + static purgeCache (projectDir) { + if (projectDir) { + delete projectFileCache[projectDir]; + } else { + projectFileCache = {}; + } + } } -AndroidProject.getProjectFile = function (projectDir) { - if (!projectFileCache[projectDir]) { - projectFileCache[projectDir] = new AndroidProject(projectDir); - } - - return projectFileCache[projectDir]; -}; - -AndroidProject.purgeCache = function (projectDir) { - if (projectDir) { - delete projectFileCache[projectDir]; - } else { - projectFileCache = {}; - } -}; - -/** - * Reads the package name out of the Android Manifest file - * - * @param {String} projectDir The absolute path to the directory containing the project - * - * @return {String} The name of the package - */ -AndroidProject.prototype.getPackageName = function () { - var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml'); - return new AndroidManifest(manifestPath).getPackageId(); -}; - -AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, src) { - // All custom subprojects are prefixed with the last portion of the package id. - // This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name. - var packageName = this.getPackageName(); - var lastDotIndex = packageName.lastIndexOf('.'); - var prefix = packageName.substring(lastDotIndex + 1); - var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src)); - return subRelativeDir; -}; - -AndroidProject.prototype.addSubProject = function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var subProjectFile = path.resolve(subDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - // TODO: Setting the target needs to happen only for pre-3.7.0 projects - if (fs.existsSync(subProjectFile)) { - var subProperties = this._getPropertiesFile(subProjectFile); - subProperties.set('target', parentProperties.get('target')); - subProperties.dirty = true; - this._subProjectDirs[subDir] = true; - } - addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir)); - - this._dirty = true; -}; - -AndroidProject.prototype.removeSubProject = function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir)); - delete this._subProjectDirs[subDir]; - this._dirty = true; -}; - -AndroidProject.prototype.addGradleReference = function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir)); - this._dirty = true; -}; - -AndroidProject.prototype.removeGradleReference = function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir)); - this._dirty = true; -}; - -AndroidProject.prototype.addSystemLibrary = function (parentDir, value) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - addToPropertyList(parentProperties, 'cordova.system.library', value); - this._dirty = true; -}; - -AndroidProject.prototype.removeSystemLibrary = function (parentDir, value) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'cordova.system.library', value); - this._dirty = true; -}; - -AndroidProject.prototype.write = function () { - if (!this._dirty) { - return; - } - this._dirty = false; - - for (var filename in this._propertiesEditors) { - var editor = this._propertiesEditors[filename]; - if (editor.dirty) { - fs.writeFileSync(filename, editor.toString()); - editor.dirty = false; - } - } -}; - -AndroidProject.prototype._getPropertiesFile = function (filename) { - if (!this._propertiesEditors[filename]) { - if (fs.existsSync(filename)) { - this._propertiesEditors[filename] = properties_parser.createEditor(filename); - } else { - this._propertiesEditors[filename] = properties_parser.createEditor(); - } - } - - return this._propertiesEditors[filename]; -}; - -AndroidProject.prototype.getInstaller = function (type) { - return pluginHandlers.getInstaller(type); -}; - -AndroidProject.prototype.getUninstaller = function (type) { - return pluginHandlers.getUninstaller(type); -}; - -/* - * This checks if an Android project is clean or has old build artifacts - */ - -AndroidProject.prototype.isClean = function () { - var build_path = path.join(this.projectDir, 'build'); - // If the build directory doesn't exist, it's clean - return !(fs.existsSync(build_path)); -}; - module.exports = AndroidProject;