Special connect() issue 2014

Volume 29 Number 12A

Cross-Platform : Write Cross-Platform Hybrid Apps in Visual Studio with Apache Cordova

Kraig Brockschmidt

Web developers with expertise in standard HTML, CSS and JavaScript already know that Web applications reach the greatest breadth of devices and customers with a single code base. And with responsive Web design, Web applications can also deliver great mobile experiences.

Yet the wind appears to be blowing elsewhere: Data shows that mobile customers spend about 80 percent of their time in apps and 20 percent in browsers. Put simply, even the best mobile Web solutions just don’t get the visibility and usage of native apps that are discoverable through platform app stores. Furthermore, although the W3C and browser vendors strive to surface native platform capabilities through new HTML5 standards, it’s a slow process. Compared with native apps and native APIs, the mobile Web and HTML5 will generally be at a disadvantage when it comes to delighting customers with new innovations.

Must you then bite the bullet and write native apps? Must you learn different languages and UI paradigms, shoulder the high cost of managing projects for each platform, and subsequently miss potential market opportunities?

Not at all! Enter the open source framework known as Apache Cordova (cordova.apache.org), managed by the Apache Software Foundation (ASF). Cordova lets you use your HTML, CSS and JavaScript skills—and vast community resources—to create apps for Android, Amazon Fire, iOS, Mac OS X, Windows, Windows Phone, BlackBerry, Web browsers and more. Better still, whereas Web applications have limited browser-supported capabilities only, the Cordova plug-in model provides full access to native platform APIs.

Thus, Cordova gives you the cross-platform benefits of the Web without sacrificing functionality, offering an attractive path for entering the mobile app marketplace. We’ll show how it all works by building the simple selfie app shown in Figure 1.

The Here My Am! App on an Android Device
Figure 1 The Here My Am! App on an Android Device

Cordova in Visual Studio

Working with Cordova is typically done through the Node Package Manager (npm) and the Cordova command-line interface (CLI). Depending on your target platform, you also need to install other components such as platform SDKs as described in the “Platform Guides” section of the Apache Cordova Documentation (bit.ly/1tJ19fq). For many developers wanting to target Android, iOS and Windows, this can be a lot of work, and it can take some time to learn all the intricacies of the different tools.

To make it easier and to bring the power and productivity of Visual Studio to Cordova, Microsoft is building the Visual Studio Tools for Apache Cordova. This toolkit—presently in preview and available as an extension for Visual Studio 2013 Update 4 (bit.ly/11m4vKH) and built into Visual Studio 2015 Preview (bit.ly/1u1dsSQ)—correctly installs and configures each third-party dependency for Android and iOS targets (Windows comes automatically with Visual Studio). It then automates Cordova processes into the Visual Studio IDE, such as installing plug-ins, running builds, and deploying to devices and emulators. Furthermore, it gives you all the goodness you expect from Visual Studio such as IntelliSense, integrated debugging, project and configuration management, integration with Visual Studio Online, and the ability to use TypeScript.

To target Android and Windows using Visual Studio, you need only a Windows 8 or higher machine (and you can do Android from Windows 7). To target iOS, you need a Mac with Xcode 5.1 or later, and you can run Visual Studio within Windows on Parallels or VMware Fusion. (See the “Install Tools to Build for iOS” MSDN Library page at bit.ly/1GqnEuK for details, including information about the remote build agent, vs-mda-remote, which runs on Macs and lets you build, run and debug from Visual Studio over a local network or VPN connection.)

Of Web Hosts and Responsive Cross-Browser CSS

We’ll call our selfie app Here My Am! (a phrase that Kraig’s son used at age 3), whose HTML5 markup is straightforward, as shown in Figure 2.

Figure 2 The HTML Markup for the Here My Am! App

<body>
  <div class="mainContainer">
    <div class="title mainChild">
      <h1 class="titlearea ">Here My Am!</h1>
    </div>
    <div id="locationSection" class="mainChild subsection">
      <h2 class="section-title">Here:</h2>
        <div id="locationControls">
          <input id="txtLocation" type="text" placeholder="tap to edit" />
            <button id="btnLocate" class="iconGlobe"></button>
        </div>
    </div>
    <div id="photoSection" class="mainChild subsection">
      <h2 id="photoHeading" class="section-title">My:</h2>
        <div id="photo">
          <img id="photoImg" src="#" draggable="false"
          alt="Tap to capture image from camera" />
        </div>
    </div>
    <div id="shareSection" class="mainChild">
      <button id="btnShare" class="shareButton" disabled>Share</button>
    </div>
  </div>
</body>

Next, we need the appropriate styling to match Figure 1, which gives us an opportunity to explore the core nature of Cordova.

Native mobile apps generally run from compiled executables: The code you write in languages such as Objective-C, Swift, Java, C# and C++ is compiled into binary formats that mobile OSes understand. HTML, CSS and JavaScript, on the other hand, must be fed to a host—such as a browser—that parses, renders and executes that source code at run time. Some platforms, such as Windows 8/8.1 and Windows Phone 8.1, provide a system-level host that renders HTML, CSS and JavaScript directly as a native app. For more on this, refer to the free ebook, “Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition” (Microsoft Press, 2014), by Kraig Brockschmidt at bit.ly/1jyOYLC. Cordova uses such a capability where possible. Otherwise, as on iOS and Android at present, it uses a browser-like WebView element inside a native app wrapper, as shown in Figure 3. Either way, you have an environment in which your Web-standards code runs in the context of an app.

Cordova Runs HTML, CSS and JavaScript Within a Native App Environment
Figure 3 Cordova Runs HTML, CSS and JavaScript Within a Native App Environment

The rub is that these host environments aren’t created equal. Each is a variant of the native browser in the OS, as shown in Figure 4.

Figure 4 Basis for Host Environments

Mobile Platform Host Basis
Windows 8/8.1, Windows Phone 8/8.1 Internet Explorer 10/11
Android 4.x, 5.0 Android Browser 4.x, 5.0 (4.4 or later is recommended for the best implementation)
iOS7, iOS8 iOS Safari 7.1/8 or later, depending on updates

Therefore, a Cordova app’s CSS must work in each target platform’s Web host, just like Web applications must work in different browsers by using a variety of prefixed and nonprefixed styles, and you can use similar approaches. It’s helpful, for example, to drop your app’s files on a Web host and open them up in Internet Explorer, Chrome and Safari (on a Mac) and then use browser developer tools to test your styling at different window sizes. Also, cross-reference your styling at caniuse.com, which identifies exactly which HTML5 and CSS3 features are supported in which browsers and mobile environments (and remember to look at the Android Browser and iOS Safari, specifically). Of course, simpler layouts will be more adaptable, and you can use CSS frameworks such as jQuery Mobile, Ionic and Bootstrap. You can also use CSS preprocessors such as LESS or SASS, which are supported as of Visual Studio 2013 Update 2, but need to be run prior to a Cordova build.

Along similar lines, mobile apps will also encounter many combinations of screen sizes and orientations, as described in Figure 5.

Figure 5 Common Screen Size Combinations

Portrait Widths/Landscape Heights Portrait Heights/Landscape Widths
240 (low-end phones) 320, 400, 480
320 (mid-level phones) 462, 480, 470, 568 and greater heights on Windows in a narrow view.
480 (mid-level phones) 640, 800, 854 and other heights on Windows in a greater-than-500-px portrait orientation.
720, 768 (tablets) 960, 1024 or larger. The iPad is 1024x768, as are some views on Windows.
Greater than 768 iPad 2 and later; most Windows laptops and tablets and many Android tablets.

All the principles of responsive Web design—using media queries to adjust margins, font sizes, layouts, animations and so on—are thus essential with Cordova apps (and to keep things simple, the Here My Am! app supports portrait mode only). Be mindful, too, that the physical screen dimensions of a device aren’t necessarily those reported to the CSS rendering engine. High-DPI displays typically have a scaling factor applied, meaning the sizes in Figure 5 apply to [min | max]-[width | height] media queries rather than [min | max]-device-[width | height] queries. In some cases the scaling might not be exact, either; a nominal 768-px dimension on an iPad might appear in CSS as 767. Test early and often, and again consider a CSS framework or preprocessing tool.

The Cordova App Project Structure

After our markup and CSS are in decent shape, we can bring them into a Cordova app. In Visual Studio, a Cordova app created with File | New | Project, selecting JavaScript | Apache Cordova Apps | Blank App (Apache Cordova), gives the project structure shown in Figure 6 (note that this is subject to change as the Tools for Cordova approach RTM).

Figure 6 Project Structure in Visual Studio

Folder or file Can rename? Description
css Yes Folder for stylesheets. The css, images and scripts folders can all be renamed arbitrarily and referenced from your HTML files.
images Yes Default (empty) folder for platform-neutral graphics.
merges No Folder for platform-specific JavaScript. The build tools depend on this folder name, as with res.
res No Folder for platform-specific resources such as icons, splash screens and manifests.
scripts Yes Default folder for JavaScript files.
config.xml No The global configuration file that conforms to the W3C Packaged Web Apps (Widgets) specification. It serves as a generic manifest whose settings translate into platform-specific manifest entries. Visual Studio provides a designer for config.xml, and you can edit the raw XML, as some settings aren’t shown in the designer.
index.html Yes Default start page for the app, referred to in the Common | Start Page field of config.xml. If you rename it, update config.xml accordingly.

For our app, we’ll drop the markup into index.html and our styles into css/index.css. We’ll also bring in the cross-platform WinJS 3.0 library for various goodies, which we’ve copied into css/frameworks, css/fonts and scripts/frameworks to keep everything organized (and of course you can use any number of other libraries such as AngularJS and Bootstrap). Here’s the <head> element of index.html:

<!-- Recommended to prevent pinch zoom in webviews -->
<meta name="viewport" content="user-scalable=no" />
<link href="css/frameworks/ui-dark.css" 
  rel="stylesheet" /> <!-- WinJS -->
<link href="css/index.css" rel="stylesheet" /> <!-- App styles -->
<script src="cordova.js"></script> <!-- Cordova standard -->
<!-- WinJS -->
<script src="scripts/frameworks/base.js"></script>
<script src="scripts/frameworks/ui.js"></script>
<script src="scripts/frameworks/winjs.js"></script>
<!-- Project references -->
<script src="scripts/platformOverrides.js"></script>
<script src="scripts/index.js"></script>

Note the reference to cordova.js, which you won’t find anywhere in your project; it’s brought in automatically as part of the build process.

As for platformOverrides.js, the file by this name in the root scripts folder is empty, but there’s another in merges/windows/scripts that loads up another file called winstore-jscompat.js (to help accommodate third-party libraries). At build time, all files and folders under merges/<platform> are copied into the final folder structure, overwriting any files with the same names in the root project. On Windows, scripts/platformOverrides.js is replaced by merges/windows/scripts/platformoverrides.js. This is how you can incorporate platform-specific code, if needed, and the same file-level merging also works for CSS, images and anything else. Just remember that it’s a file-level merge, not a merging of file contents! Also note that the merges folder might be deprecated in favor of feature-detection approaches.

The contents of the res folder have a similar but more varied behavior because these resources are needed for the app package, rather than the code running inside the WebView or host. Remember that Cordova builds a native app wrapper around a WebView when necessary, meaning that it creates a folder structure for the native app package as required by the target platform. Figure 7 illustrates where different parts of the Visual Studio project end up in a build. You can see the results if you build a project and then open the bld/debug/platforms folder. We will use this behavior later on to customize the Windows/Windows Phone app manifests.

How Different Parts of a Source Project End Up in Platform-Specific Build Folders
Figure 7 How Different Parts of a Source Project End Up in Platform-Specific Build Folders (Subject to Change)

Native APIs and Plug-Ins

We’re now ready to add behaviors in JavaScript to our app. By default, the Cordova app template in Visual Studio supplies the code shown in Figure 8 (most comments omitted), where the Cordova deviceready, pause and resume events abstract similar app lifecycle events on various platforms (see the “Events” section of the Apache Cordova Documentation at bit.ly/1u1hT1n for the full roster).

Figure 8 Default Code from the Cordova App Template

(function () {
  "use strict";
  document.addEventListener('deviceready', 
    onDeviceReady.bind(this), false);
  function onDeviceReady() {
    document.addEventListener('pause', onPause.bind(this), false);
    document.addEventListener('resume', onResume.bind(this), false);
    // Perform other initialization here.
  };
  function onPause() {
  };
  function onResume() {
  };
} )();

For simplicity, we won’t be persisting any data in Here My Am!, so we’ve removed the pause and resume handlers.

Note that deviceready typically fires after DOMContentLoaded, so you can do DOM-related initialization within your deviceready handler. In some debugging scenarios, however, such as using Visual Studio remote debugging over a wireless network, it’s possible for deviceready to fire before DOMContentLoaded, leading to null object exceptions. Here My Am! uses some flags to handle this variance.

Here’s what we now need to do in our app:

  • Initialize the Here field with the user’s location and wire up the locate button.
  • Initialize the photo area with the default message and wire it up to camera capture.
  • Enable sharing the location and image.
  • Lock the display orientation to portrait.

Although we could use the HTML5 geolocation API and write a bunch of code to share to specific social networks, we start running into problems with camera capture because of two primary WebView limitations that can affect Cordova development (for example, on iOS and Android):

  1. WebViews block JavaScript from accessing any native platform APIs because untrusted JavaScript code loaded from a potentially remote source poses a security threat. (On Windows platforms, in-package JavaScript is trusted and can call native APIs, but remotely loaded script can’t.)
  2. WebViews typically support only a subset of HTML5 APIs (varied by platform, check caniuse.com), and many native capabilities are far from having suitable HTML5 standards.

Fortunately, a native app and any WebView it contains can communicate through special mechanisms provided by the OS. Cordova abstracts these mechanisms through plug-ins as illustrated in Figure 9. Simply put, a plug-in contains a universal JavaScript interface that’s loaded into the WebView, which in turn uses the platform’s communication channel to talk to a piece of native code that’s compiled for that platform and can use native APIs. Again, where the underlying platform supports native JavaScript apps, it’s not necessary to go through such a bridge, but plug-ins still serve to abstract platform differences.

The Structure of Cordova Plug-ins When Bridging Is Required, as on iOS and Android
Figure 9 The Structure of Cordova Plug-ins When Bridging Is Required, as on iOS and Android

The ASF provides a core set of Cordova plug-ins for common native APIs such as storage, media, networking, geolocation, sensors, dialogs, media capture, notifications, device information and globalization. When you select these plug-ins within the Visual Studio config.xml editor, the appropriate code is pulled into your builds automatically.

You can also browse the healthy ecosystem of third-party plug-ins on the Cordova Plugins Registry (plugins.cordova.io) and other sites such as plugreg.com. These cover all manner of features including advertising, Microsoft Azure Mobile Services, Bluetooth communication, social sharing and much more. And because plug-ins aren’t obligated to simply surface native APIs on a 1-to-1 basis, plug-in developers often add value by building higher-level capabilities such as barcode scanning and integration with Web services. A great example is the plug-in for Cortana, the vocal assistant for Windows Phone. Developed by Microsoft Open Technologies Inc., a wholly owned subsidiary of Microsoft focusing on open source technologies, it was warmly received by developers at a PhoneGap Day in October 2014. Be mindful, though, that platform support varies widely among plug-ins. For example, the Cortana plug-in supports only Windows Phone 8.1.

Whatever the case, the Visual Studio config.xml editor helps you easily pull plug-ins into your project from sources such as the Cordova registry or GitHub, as described in the MSDN Library article, “Manage Plugins for Apps Built with Visual Studio Tools for Apache Cordova,” at bit.ly/10ov6Fo. We’ll present an example shortly. Visual Studio automatically pulls in the right files so the appropriate methods get added to the global namespace without you having to explicitly reference a plug-in’s JavaScript file.

Overall, when thinking about native APIs, the convention with Cordova is to first look for a suitable plug-in rather than adding platform-specific code to your app. If you find one that’s close to what you want, consider extending it—after all, many are written by developers such as you, and contributions are welcome on GitHub. Otherwise, refer to the “Plugin Development Guide” section of the Apache Cordova Documentation to create a plug-in of your own that you can then share with the Cordova community.

Completing the App

Knowing how we access native APIs through plug-ins, we can complete the features of our app. For geolocation, we pull in the Cordova Geolocation plug-in and add this code to our deviceready handler to initialize the location field and wire up the locate button:

locate();
document.getElementById("btnLocate").addEventListener("click", locate);

Then we implement the locate method, as shown in Figure 10.

Figure 10 Implementing Geolocation

function locate() {
  navigator.geolocation.getCurrentPosition(function (position) {
    App.lastPosition = {
      latitude: position.coords.latitude, 
        longitude: position.coords.longitude,
      address: "(" + position.coords.latitude + ", 
        "      + position.coords.longitude + ")"
    };
    // Go translate the coordinates into an address using the Bing Map Web API.
    updatePosition();
  }, function (error) {
    WinJS.log && WinJS.log("Unable to get location: "
     + error.message, "app");
  }, {
    maximumAge: 3000, timeout: 10000, enableHighAccuracy: true
  });
}

Wait a minute—isn’t navigator.geolocation just the HTML5 API? Well, maybe: The plug-in intelligently uses the HTML5 implementation if it’s available, otherwise it adds the same functions to the global namespace that are implemented using native APIs (or fails gracefully if there’s no platform support). This way, code migrated from a Web site doesn’t have be rewritten.

Having obtained the location, we store the coordinates in App.lastPosition and create a default App.address string we use for the txtLocation UI element and sharing. Our updatePosition function (not shown) then attempts to use the Bing Maps Web API to translate those coordinates into a meaningful address before setting the txtLocation value. Refer to the accompanying code download for details.

For camera capture, we initially create a default image and wire up the photo area to do the capture:

setPlaceholderImage();
document.getElementById("photo").addEventListener("click",
  capturePhoto.bind(photo));

Adding the Cordova Camera plug-in adds the method naviga­tor.camera.getPicture to the global namespace. If successful, this call provides a URI to an image on the device’s local file system, which we can just assign to an img.src attribute. In the code shown in Figure 11, the assignment happens within our scaleImageToFit function that does letterboxing to preserve the image’s aspect ratio.

Figure 11 Working with the Cordova Camera Plug-In

function capturePhoto() {
  var photoDiv = this;
  // Capture camera image into a file.
  navigator.camera.getPicture(cameraSuccess, cameraError, {
    quality: 50,
    destinationType: Camera.DestinationType.FILE_URL,
    encodingType: Camera.EncodingType.JPEG,
    mediaType: Camera.MediaType.PICTURE,
    allotEdits: true
    correctOrientation: true // Corrects Android orientation quirks.
  });
  function cameraSuccess(imageFile) {
    // Save for share and enable Share button.
    App.lastCapture = imageFile;
    document.getElementById("btnShare").disabled = false;
    // Do letterboxing and assign to img.src.
    scaleImageToFit(photoDiv.querySelector("img"), 
      photoDiv, App.lastCapture);
  };
  function cameraError(error) {
    WinJS.log && WinJS.log("Unable to obtain picture: " + error, "app");
  };
}

To implement sharing, which is enabled when we have an image, we found Eddy Verbruggen’s Social­Sharing plug-in on plugreg.com, which works with both text and images. When we add it as a custom plug-in directly from GitHub, as shown in Figure 12, Visual Studio downloads everything we need automatically. (This process downloads everything from the repository, but the only essential parts are the plug-in’s plugin.xml file and the src and www folders; everything else can be removed.)


Figure 12 Adding a Custom Plug-in from GitHub

Now we can wire up the Share button and call the plug-in’s socialsharing.share API (in the window.plugin namespace) to get the lovely UI shown in Figure 13 that provides a variety of sharing choices similar to the Share charm on Windows 8/8.1:

document.getElementById("btnShare").addEventListener("click", App.share);
function share() {
  var txtLocation = document.getElementById("txtLocation").value;
  plugins.socialsharing.share("At " + txtLocation, "Here My Am!",
    App.lastCapture);
}

Sharing on Android, iOS and Windows Phone 8
Figure 13 Sharing on Android, iOS and Windows Phone 8 (Images Courtesy of the SocialSharing Plug-In)

But there’s a snag: SocialSharing supports Android, iOS and Windows Phone 8, but not Windows 8/8.1 and Windows Phone 8.1. Quite a few third-party plug-ins have limited platform support, in fact, presenting clear opportunities to help improve the plug-in for the community’s benefit. For this article, though, it gives us a chance to demonstrate using the merges folder, because a Cordova app on Windows runs within the system host where we can call native APIs directly from JavaScript and bypass the plug-in altogether.

First, we’ll move the aforementioned share function into a share.js file and expose it as App.share:

WinJS.Namespace.define("App", {
  configurePlatformSharing: function () { },
  share: share
});
function share() {
  var txtLocation = document.getElementById("txtLocation").value;
  plugins.socialsharing.share("At " + txtLocation, "Here My Am!",
    App.lastCapture);
}

Next, in merges/windows/share.js, which will replace the platform-neutral share.js, we provide a different App.share function that invokes the Share charm:

function share() {
  Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();
}

To make this work, though, we must wire up a handler during initialization for the DataTransferManager.ondatarequested event. This is the purpose of the stub method configurePlatformSharing, which does nothing on non-Windows platforms when we call it in the deviceready handler:

App.configurePlatformSharing();
In the Windows-specific share.js, however, we do more:
WinJS.Namespace.define("App", {
  configurePlatformSharing: configurePlatformSharing,
  share: share
});
function configurePlatformSharing() {
  var dataTransferManager = 
    Windows.ApplicationModel.DataTransfer.
    DataTransferManager.getForCurrentView();
  dataTransferManager.addEventListener("datarequested", provideData);
}

In the preceding code, provideData creates the appropriate data package, the result of which is a native Share charm experience on Windows 8.1 and Windows Phone 8.1, as shown in Figure 14.

Sharing on Windows 8.1 and Windows Phone 8.1
Figure 14 Sharing on Windows 8.1 and Windows Phone 8.1

The last piece of our app is to enforce a portrait-only view, which gives us an opportunity to see how we have full control over platform-specific manifests when necessary via the res/native folder. In this case, setting the Common | Orientation to Portrait in the config.xml editor is sufficient for Android, but as of this writing doesn’t affect Windows and Windows Phone. No problem—we can just make some custom entries in the app manifests.

To do this, run a build and go to bld/platforms/windows where you’ll find generated manifests named package.windows.appxmanifest (Windows 8.1), package.phone.appxmanifest (Windows Phone 8.1), and package.windows80.appxmanifest (Windows 8). Copy whichever ones you need into res/native/windows and make your changes. To enforce portrait orientation, this is all we need within the Application | Application | VisualElements node (shown for Windows 8.1; use the namespace prefix m3: for Windows Phone 8.1 and no prefix for Windows 8):

<m2:InitialRotationPreference>
  <m2:Rotation Preference="portrait" />
  <m2:Rotation Preference="portraitFlipped" />
</m2:InitialRotationPreference>

At build time, Cordova translates the start page setting and individual preferences in config.xml to the platform-specific manifest, along with platform-specific details from plug-ins. Specifically, if you look in the plugin.xml file in any plug-in folder, you’ll see entries such as this:

<platform name="windows">
  <config-file target="package.windows.appxmanifest"
    parent="/Package/Capabilities">
    <Capability Name="picturesLibrary" />
    <DeviceCapability Name="webcam" />
  </config-file>  <!-- ... -->
</platform>

The preceding code says, “For Windows targets, in the package.windows.appxmanifest file, add these Capability and DeviceCapability elements under the Package | Capabilities node.” So, clearly, an orientation plug-in could do the same job we’ve done manually. And with that, we have a functional app!

Debugging, Deployment and Other App Lifecycle Concerns

As a developer, you clearly know that writing code is just one part of the overall process of producing market-ready software, and Visual Studio has quite a bit to offer here, as shown in Figure 15.

Figure 15 Additional Visual Studio Features for Cordova Apps

Feature Description/Notes
Debugging

At the time of writing, the following devices and emulators support debugging in Visual Studio with the JavaScript Console and DOM Explorer:

  •    Android 2.3.3 and later (4.4 or later is best)
  •    iOS 6, 7, 8
  •    Windows 8 and 8.1
  •    Apache Ripple (Chrome-based emulator) for Android and iOS

Debugging on Windows Phone 8 and 8.1 isn’t presently supported, but you can use the Web Inspector Remote (weinre) as described in a Microsoft Open Technologies blog post at bit.ly/1y9k0zr.

When running in Ripple, you might encounter the infamous message, “I Haz Cheeseburger?!?!” For information on this, refer to the Visual Studio Tools FAQ at bit.ly/1x71P0q, and when in doubt, just hit the Success button. There’s also a note in the default index.js file that says to run the window.location.reload function in the JavaScript Console to debug initialization code; be mindful that this reloads the most recent build and doesn’t rebuild the app or apply any changes to source files.

IntelliSense Visual Studio gives you IntelliSense on HTML, CSS and JavaScript code, including a growing number of third-party libraries such as JQuery, Backbone.js and Require.js.
Test Appium and Chutzpah are popular open source automation tools. The Chutzpah Test Runner for Visual Studio integrates with the Visual Studio Test Explorer and Team Foundation Build. For broad device testing you can use services such as Perfecto Mobile.
Application Lifecycle Management Visual Studio ALM features provide for agile planning, source control (hosted on Team Foundation Server or GitHub), team collaboration, and release management for cross-platform projects and team members using other IDEs.

It’s helpful to know as you step into building Cordova apps that you’ll find quirky behaviors on every platform. This is just the nature of cross-platform development at present, which means you should realistically expect to do as much per-platform debugging as you would writing native apps for each target. Similarly, deployment happens with each app store individually, using tools specific to those platforms. Cordova doesn’t shortcut those processes.

The platform-specific builds will pull in the appropriate resources in your project’s res folder: Be sure to review that content and confirm you have all the right graphics and other files for each platform. When getting your final package together, also double-check the manifests to make sure your app and your company are correctly identified and that you’re not carrying over data from the default project template.

And when your app is ready to go out to real customers, dedicate yourself to responding to issues with timely app updates. There’s so much device variance within the realm of even a single platform that customers will effectively be your field testers—be sure to honor that role with quick updates.

What to Expect in Upcoming Visual Studio Releases

In closing, we’ve already seen how Visual Studio Tools for Apache Cordova go a long way to simplifying cross-platform Cordova development. Microsoft Open Technologies is a significant contributor to the Cordova project itself, and the Visual Studio Tools team is committed to making the experience even better—what we’ve covered in this article is just a preview! Moving forward, the team is looking at app features such as push notifications, greater IntelliSense, better debugging on more platforms, HTML/CSS designers, improved support for unit testing, support for Team Build, and speeding up and supporting the standard Web developer workflow. Are there other features you’d like to see? Give us your feedback through the Microsoft UserVoice site (visualstudio.uservoice.com) or @VSCordovaTools on Twitter, and join the discussion about the toolkit on StackOverflow (bit.ly/1yCReYa).

Tips, Tricks and Notes

Moving targets: To easily switch between target platforms, add the Solution Platforms control to your toolbar as described in the MSDN Library article, “Create Your First Hello World App,” at bit.ly/1th836k.

PhoneGap and Cordova: Cordova began as a mobile framework and build system called PhoneGap produced by Nitobi Software Ltd., designed to bridge the gap between different mobile phone platforms by abstracting differences behind a framework. Adobe Systems Inc. acquired Nitobi in 2011 and subsequently open sourced the framework to the Apache Software Foundation as Apache Cordova, to which Microsoft Open Technologies Inc. is a significant contributor. Adobe runs the cloud-based PhoneGap Build system that creates native app packages from Web code so you don’t need native SDKs on your own machine.

Android Emulators: There’s near-universal agreement in the developer community that the raw Android SDK emulators are worth avoiding like dial-up Internet unless you configure virtual machine (VM) acceleration. Visual Studio 2015 Preview includes the fast Hyper-V/x86-based Visual Studio Emulator for Android (bit.ly/1xlRwFT), which is compatible with the Windows Phone Emulator (and which, once installed, works with Visual Studio 2013 Update 4). You can also use the GenyMotion Emulator for Android if you don’t want to install the Visual Studio 2015 Preview.

Cordova’s Sweet Spot: Developers generally realize that running HTML, CSS and JavaScript inside a Cordova app won’t always produce a truly native experience on every platform. Cordova apps, then, are ideal for highly branded experiences that needn’t conform to native UI patterns, and for enterprise apps where differentiation across platforms isn’t desired. Cordova is also an efficient means to quickly build production apps that test ideas in the marketplace, helping you understand where to make deeper business investments.

Referencing Remote Script: Web applications often load JavaScript libraries from remote sources, which makes sense because a user has to be online to see the Web site at all. Mobile apps, however, should provide a great experience without connectivity, so it’s best to download remote script and include it directly in your project. This is required on Windows 8/8.1 and Windows Phone 8.1 where the system host disallows remote script; loading a library that attempts to load other remote script can be problematic here, and you might need to do some manual patching to make it all work.

One Platform at a Time: Using a cross-platform tool such as Cordova doesn’t mean you must ship an app on multiple platforms simultaneously. You might target only a single platform initially, knowing that your investments will apply to other platforms later. This way you can optimize your UI and CSS for one platform at a time.


Kraig Brockschmidt works as a senior content developer in the Microsoft Developer Division and is focused on providing developer guidance for mobile cloud-connected apps on Windows, iOS and Android. He’s the author of “Programming Windows Store Apps with HTML, CSS and JavaScript” (two editions) from Microsoft Press and shares other insights on kraigbrockschmidt.com/blog.

Mike Jones is a programmer writer who’s been working on mobile at Microsoft for 10 years, from Compact Framework to Silverlight for Windows Phone to Visual Studio Tools for Apache Cordova. He's been enjoying JavaScript for the last few years after a long, fun fling with C#, et al.

Thanks to the following Microsoft technical experts for reviewing this article: Chuck Lantz, Eric Mittelette, Parashuram Narasimhan, Ryan Salva, Amanda Silver, Cheryl Simmons and Priyank Singhal