The Cordova integration allows running, building and testing of Cordova projects from the CLI.
It hooks into the following commands:
cli/commands.js
:meteor run/test-packages/build
cli/commands-cordova.js
:meteor add-platform/remove-platform/list-platforms
cli/commands-packages.js
:meteor add/remove cordova:<plugin>
These commands call into functionality provided by the classes under cordova/
(CordovaProject
, CordovaBuilder
, CordovaRunner
, and CordovaRunTarget
),
as well as some utility functions in cordova/index.js
(generally imported
under the cordova
namespace).
CordovaProject
(in project.js
) represents the generated Cordova project (in
the .meteor/local/cordova-build
directory), and is the only class with a
direct dependency on cordova-lib
. Its methods allow you to call into the
prepare, build and run stages, and manage platforms and plugins.
In this version, we've switched from relying on Cordova CLI to using
cordova-lib
directly. This avoids multiple levels of script invocations, which
leads to difficult to diagnose failures and makes it harder to support Windows.
Old situation: Meteor CLI → Meteor Cordova wrapper scripts → Cordova CLI → Cordova platform-specific scripts
New situation: Meteor CLI + cordova-lib
(in-process) → Cordova
platform-specific scripts
Commands in cordova-lib
are invoked asynchronously (they return promises) but
for the most part we wait with Promise.await
. This is abstracted away in
runCommands
. There is some other code in CordovaProject
that helps with
setting the cwd
and env
and catching CordovaError
s.
CordovaProject#createIfNeeded()
Invoked automatically from the constructor. Makes sure the project has been
created if the cordova-build
directory does not currently exist.
CordovaProject#prepareFromAppBundle(bundlePath, pluginVersions, options = {})
Uses a builder (see CordovaBuilder
) to generate the www
directory,
resources, and config.xml
based on the app bundle result and
mobile-config.js
.
CordovaProject#prepareForPlatform(platform)
Similar to cordova prepare <platform>
. Synchronizes the project contents
(www
directory and resources) with a platform directory and installs or
updates plugins in a platform-specific manner (modifying an Xcode project for
instance).
CordovaProject#buildForPlatform(platform, options = {}, extraPaths)
Similar to cordova build <platform>
. Uses platform-specific build mechanisms
to compile app. Includes everything done in the prepare stage. It is used for
meteor build
.
async CordovaProject#run(platform, isDevice, options = [], extraPaths)
Similar to cordova run <target>
, except that it doesn't include prepare, so
you'll have to make sure CordovaProject#prepareForPlatform()
is called before.
Uses platform-specific mechanisms to run the built app on a device or
emulator/simulator. It is used for meteor run/test-packages
.
CordovaProject#ensurePlatformsAreSynchronized(platforms = this.cordovaPlatformsInApp)
Ensures the platforms installed in the Cordova project are synchronized with the
app-level platforms (in .meteor/platforms
). This gets invoked as part of
meteor add-platform/remove-platform
(from commands-cordova.js
) and as part
of the build process (from CordovaBuilder
).
Uses methods CordovaProject#listInstalledPlatforms()
,
CordovaProject#addPlatform(platform)
, and
CordovaProject#removePlatform(platform)
to call into Cordova.
CordovaProject#checkPlatformRequirements(platform)
uses the Cordova
platform-specific tools to get a list of installation requirements, whether they
are satisfied, and if not, why. The latter can be very useful and is pretty
detailed (telling you for instance that ANDROID_HOME
has been set to a
non-existent directory, or that the right platform tools cannot be found).
We massage the results a little and print them (only if not all requirements for a platform are satisfied) in a list with checkmarks and crosses. This may need some work. We probably want to simplify the results a little and only show the full list in a verbose mode. And we definitely want to add a link to a Wiki page with installation instructions.
This gets invoked from meteor add-platform
(so we can immediately give
feedback about the state of the installation) and before running (from
runner.checkPlatformsForRunTargets()
).
CordovaProject#ensurePluginsAreSynchronized(pluginVersions, pluginsConfiguration = {})
Ensures the plugins installed in the Cordova project are synchronized with the
app-level Cordova plugins. This gets invoked as part of the build process (from
CordovaBuilder
) where it is passed the plugins from the star manifest in the
app bundle (pluginVersionsFromStarManifest
, a combination of
.meteor/cordova-plugins
for stand-alone plugin installs and the plugins added
as dependencies of packages through Cordova.depends
).
The pluginsConfiguration
comes from App.configurePlugin
calls in
mobile-config.js
.
Uses methods CordovaProject#listInstalledPluginVersions()
,
CordovaProject#addPlugin(name, version, config)
,
CordovaProject#removePlugins(plugins)
to call into Cordova.
CordovaRunner
(in runner.js
) represents running the app on a set of run
targets. It holds a reference to a cordovaProject
and an array of
runTargets
. It is created in meteor run/test-packages
in cli/commands.js
and gets passed to AppRunner
.
This is a change from the previous behavior, where the Cordova build and run had to be completed before we could start the proxy, MongoDB, and bundle and run the server app.
One of the main benefits of this is that we can now use the app bundle generated
in AppRunner
. Previously, we were actually doing a whole separate
bundler.bundle()
for Cordova, even though the one in AppRunner
also
generated the web.cordova
architecture (which is needed to serve it to clients
as part of Hot Code Push). We now invoke CordovaRunner#prepareProject()
with
the existing bundle result right before starting the server app.
Moving building/running of Cordova apps to AppRunner
should also allow Cordova
apps to participate in the reload/fix cycle. (We will need to figure out how to
best do this. This may also tie in with detecting changed platforms/plugins,
automatically restarting the Cordova app when we add a plugin for instance).
CordovaRunTarget
(in run-targets.js
) represents a target to run the app on.
It has subclasses iOSRunTarget
and AndroidRunTarget
that contain some
platform-specific behavior (this will be more when we add log tailing again).
Right now, we only differentiate between running on a device or an
emulator/simulator. We may want to allow specifying a specific device ID in the
future (so we can select between different connected devices for instance).
CordovaRunner#startRunTargets()
is responsible for starting the app on the
associated run targets (while displaying build messages and a run log entry). It
currently starts the targets asynchronously (in parallel). This means running
the app on multiple targets is a lot faster than before. Because we don't
currently have a way of showing multiple progress bars, it may be confusing to
see 'Started app on Android emulator` while the build/run is still in progress.
CordovaBuilder
(in builder.js
) represents the process of building a Cordova
project from an app bundle. It contains state (metadata
,
additionalConfiguration
, accessRules
, imagePaths
, pluginsConfiguration
)
that is built-up through different stages (initalizeDefaults()
,
processControlFile()
) and can be used to generate and copy the www
directory, resources, and config.xml
.
CordovaBuilder#processControlFile()
is responsible for running the
mobile-config.js
control file (passing itself as a context to App
).