Friday, April 24, 2015

What is Visual Studio TACO ??

I consider myself fairly well informed when it comes to Visual Studio tools and tech. So when I heard the new acronym "TACO", as in:

Visual Studio 
TACo

...I was a bit humbled when I had no idea what that thing was! It turns out that this a codename for Tools for Apache Cordova, the awesome Visual Studio extension that lets you create cross-platform hybrid apps for iOS, Android and Windows!

Mind you, this is a codename only, not an official name - we all know what happens with cool sounding official names...  but if you see the TACO acronym in the future, at least you will know what it's all about.


Thursday, January 29, 2015

Using Crosswalk with Visual Studio Tools for Apache Cordova

UPDATE 1/30/2015: You can also see a video walkthrough of these steps.

If you've tried targeting Android devices using Hybrid app frameworks, you've probably run into issues with performance and outdated Chrome runtimes in the WebView. This is an issue with even newer devices with Android 4.4+ because the WebView does not use the same version of Chrome that the device has installed. For example, a Nexus 7 with Android 4.4.4 will use version 33 of Chrome - which is ancient in internet time! That means you are missing out on great features such as WebGL Support in Hybrid apps.

Enter the Crosswalk Project - which allows you to deploy the latest builds of Chromium with your Android app, and support all Android 4.x devices with the same featureset.


What is the downside you ask? The main downside the size of your deployed app. You can expect the Crosswalk library to add about 15 MB to your APK if you target _either_ ARM or x86. If you choose to target _both_ with a single APK, you can expect about 30 MB added to the size. This is an unfortunate amount of bloat, but for some apps it might be just fine. But there are other downsides as well... Don't expect Debugging Support when using Visual Studio Tools for Apache Cordova (at least not in CTP3). You can however use Chrome DevTools to debug Crosswalk apps. Also in my experience, Emulator support is hosed as well - you will need a physical device to test and run your apps.

But if you determine the benefits of Crosswalk outweigh the limitations, read on!

Adding Crosswalk Support to a Visual Studio Tools for Apache Cordova project

  1. Before you start:

    Download and Expand the Cordova Android (ARM) and Cordova Android (x86) packages. IMPORTANT: Make sure you get the Cordova versions!!

    If you are doing this to an existing project, be sure you are checked into source control, or at least back up your project! Just in case something goes wrong.

    Note that these instructions are for CTP3 of VS Tools for Apache Cordova. In later versions, these steps will surely change.

    You will need a physical Android device (I am using a Nexus 7)
  2. Create a new Visual Studio project using the Blank App template:

  3. Change your target to Android / Device:

  4. Run the Project so that it deploys to the device and runs.
  5. Open up Chrome and enter the url "chrome://inspect" - and note that the version of the Chrome WebView on the device is ancient history (in the case of the Nexus 7, it is 33.0.0.0).

  6. Back in Visual Studio, in the Solution Explorer select "Show All Files."
  7. NOTE: In the following steps, we will be adding a bunch of files to the \res\native\android folder of the project. The content of this folder is automatically included in your Android app by VS at build time.
  8. Make a copy of the AndroidManifest.xml file in

    \bld\Debug\platforms\Android to

    \res\native\android 
  9. Edit the copy you made of AndroidManifest.xml in \res\native\android so that it includes the following permissions just _before_ the <application> node.

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  10. Create a new folder named CordovaLib inside the \res\native\android\ folder of your project.

  11. The Crosswalk packages you downloaded in Step 1 are needed now.

    copy the entire contents of the ARM directory

            \crosswalk-cordova-10.xx.xxx.xx-arm\framework

    to your project's

            \res\native\android\CordovaLib\
  12. Copy the VERSION file from

            \crosswalk-cordova-10.xx.xxx.xx-arm\VERSION

    to your project's

            \res\native\android\CordovaLib\VERSION
  13. If you want x86 support as well, copy the x86 folder from

            \crosswalk-cordova-10.xx.xxx.xx-arm\framework\xwalk_core_library\libs\

    to your project's

            \res\native\android\CordovaLib\xwalk_core_library\libs
    ... so that it you have both the x86 and armeabi-v7a folders in the libs directory.
  14. Go back to Solution Explorer and be sure to include all of the files we just added into your project (Show All Files, Refresh, and then right-click all files, Include in Project).
  15. Now we have to build the libs for Crosswalk.

    You only need to do this once.

    Open a command prompt at \res\native\android\CordovaLib and execute:

    android update project --subprojects --path . --target "android-19"
    ant debug

    ... you should see a BUILD SUCCESSFUL at the finish.
  16. Close any of the open cmd prompts and File Explorer Windows, as the VS build process attempts to delete some of these folders.
  17. Back in Visual Studio, select Build/Rebuild Solution.
  18. Run the project on the device using F5. You will get an ugly dialog saying "Unable to start progam .... android_sdk\platform-tools\adb.exe" - From what I gather, this is because VS cannot attach it's debugger. You can use ChromeDev tools to debug, however.
  19. To verify we are using Crosswalk, go back to Chrome and enter the URL chrome://inspect. You will see a much newer version of Chrome (in my case 39.0.2171.71):












    That's it! We now have all of the goodness of a new Chromium runtime in our Android app, including toys like WebGL Support and improved performance!








Monday, January 19, 2015

Using Ionic with Windows 8, Windows Phone + Cordova

Ionic has been gaining in popularity as a free and open source mobile development framework. It leverages AngularJS and SASS to provide a quick start to mobile development for iOS, Android and Windows.

But getting Ionic to work when targeting Windows 8 or Windows Phone apps with CTP3 of Visual Studio Tools for Apache Cordova isn't quite straightforward due to some security context restrictions in Windows 8 apps.

So here is a walk through for getting started with Ionic in VSCordova, along with the "gotchas" for Windows apps:
  1. First note that these steps are for CTP3 of VSCordova! Future releases will likely fix some of the issues presented here.
  2. Create a new Blank App (Apache Cordova) project:

  3. Install Ionic. Here we will use Nuget, but in the future you will likely be able to use Bower for JS packages.
    • Select Tools / NuGet Package Manager / Package Manager Console
    • type in:

      Install-Package ionic
    • be patient, this takes a bit

  4. Install JQuery 2. This is required because it fixes some security context restrictions in Win8 apps.
    • From the NuGet prompt, type in:

      Install-Package jQuery
  5. Let's replace the contents of index.html with a basic ionic template and the required includes:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
        <title>Ionic VSCordova</title>
        <link href="Content/ionic.css" rel="stylesheet" />
        <link href="css/index.css" rel="stylesheet" />
        <script src="cordova.js"></script>
        <script src="scripts/platformOverrides.js"></script>
        <script src="scripts/jquery-2.1.3.js"></script>
        <script src="scripts/ionic.bundle.js"></script> 
        <script src="scripts/index.js"></script>
    </head>
    <body ng-app="ionicApp" ng-csp>

        <ion-nav-bar class="bar-positive">
            <ion-nav-back-button class="button-icon ion-arrow-left-c">
            </ion-nav-back-button>
        </ion-nav-bar>

        <ion-nav-view></ion-nav-view>

        <script id="templates/tabs.html" type="text/ng-template">
            <ion-tabs class="tabs-icon-top tabs-positive">

                <ion-tab title="Home" icon="ion-home" href="#/tab/home">
                    <ion-nav-view name="home-tab"></ion-nav-view>
                </ion-tab>

                <ion-tab title="About" icon="ion-ios7-information" href="#/tab/about">
                    <ion-nav-view name="about-tab"></ion-nav-view>
                </ion-tab>

                <ion-tab title="Contact" icon="ion-ios7-world" ui-sref="tabs.contact">
                    <ion-nav-view name="contact-tab"></ion-nav-view>
                </ion-tab>

            </ion-tabs>
        </script>

    </body>

    </html>

  6. Now let's add in our Angular code to initialize our controller and set up our views. Open index.js and paste the following code right after the:

    "use strict";

     
       var app = angular.module('ionicApp', ['ionic'])

        app.config(function ($stateProvider, $urlRouterProvider) {

            $stateProvider
              .state('tabs', {
                  url: "/tab",
                  abstract: true,
                  templateUrl: "templates/tabs.html"
              })
              .state('tabs.home', {
                  url: "/home",
                  views: {
                      'home-tab': {
                          templateUrl: "partials/home.html",
                          controller: 'HomeTabCtrl'
                      }
                  }
              })
              .state('tabs.personnel', {
                  url: "/personnel",
                  views: {
                      'home-tab': {
                          templateUrl: "partials/personnel.html",
                          controller: 'PersonnelTabCtrl'
                      }
                  }
              })
              .state('tabs.about', {
                  url: "/about",
                  views: {
                      'about-tab': {
                          templateUrl: "partials/about.html"
                      }
                  }
              })
              .state('tabs.contact', {
                  url: "/contact",
                  views: {
                      'contact-tab': {
                          templateUrl: "partials/contact.html"
                      }
                  }
              });

            $urlRouterProvider.otherwise("/tab/home");

        })

        app.controller('HomeTabCtrl', function ($scope) {
            console.log('HomeTabCtrl');
        });

        app.controller('PersonnelTabCtrl', function ($scope) {
            $scope.items = [
                { id: 1, name: "Kirk, James T." },
                { id: 2, name: "McCoy, Leonard" },
                { id: 3, name: "Scott, Montgomery" },
                { id: 4, name: "Uhura, Nyota" },
                { id: 5, name: "Sulu, Hikaru" },
                { id: 6, name: "Chekov, Pavel" },
                { id: 7, name: "Chapel, Christine" },
                { id: 8, name: "Rand, Janice" }
            ];
        });



  7. The code above references four partials: about, contact, home, and personnel. Let's go ahead and create those. Create a new subfolder in the project named "partials" and add the following files:

    about.html
    contact.html
    home.html
    personnel.html


    Inside each of the four partials above, create an ionic view and add some content inside (it doesn't matter what, be creative)... and set the view-title to an appropriate string to display in the header.

  8. <
    ion-view view-title="About">
        <ion-content class="padding">
            <p>ABOUT: this is just a little demo of Ionic working in VSCordova!</p>
        </ion-content>
    </ion-view>
  9. For home.html, let's add a View that links to personnel.

  10. <
    ion-view view-title="Home">
        <ion-content class="padding">
             <a class="button icon icon-right ion-chevron-right" href="#/tab/personnel">Personnel List</a>
        </ion-content>
    </ion-view>
  11. For the personnel.html, let's show an ionic list:

  12. <
    ion-view view-title="Personnel">
        <ion-content class="padding">
            <p>This ion list directive is great, but be sure to also checkout the collection repeat directive when scrolling through large lists.</p>
            <ion-list>
                <ion-item ng-repeat="item in items"
                          item="item">
                    {{ item.id }}: {{ item.name }}
                </ion-item>
            </ion-list>
            <p>
                <a class="button icon ion-home" href="#/tab/home"> Home </a>
            </p>
        </ion-content>
    </ion-view>

  13. Run the project using the Windows or Windows Phone Emulator, and you'll get an ugly blank screen! If you look at the JavaScript Console in Visual Studio, you will see:

    Error: [$compile:tplrt] Template for directive 'ionTabNav' must have exactly one root element. 

    This error in CTP3 is due to an issue in winstore-jscompat.js, which is used by the Cordova tooling to wrap security context issues in Win8 Store apps. To fix this problem, open the following file in the project:

    \merges\windows\scripts\winstore-jscompat.js

    ... and replace it with the fork provided here:

    https://github.com/ClemMakesApps/winstore-jscompat/blob/master/winstore-jscompat.js
  14. Run the project again, and you should be good to go! Here is a screenshot of Ionic running in a Windows Phone 8 Emulator...



Sunday, January 18, 2015

Visual Studio Cordova "The certificate specified has expired"

If you have been using a recent CTP of Visual Studio Tools for Apache Cordova to target Windows 8 apps, you may have recently hit this error on build:

Error 104 The certificate specified has expired. For more information about renewing certificates, see http://go.microsoft.com/fwlink/?LinkID=241478.


It turns out that this is an issue with the underlying Cordova support for Windows 8, which contains a recently expired certificate - as explained here. The certifcate expired on 11/11/2014.

UPDATE 1/18/2015: It appears the issue appeared again with another expired certificate. Please see this post for details on how to correct the issue for a single project (option 1) and for all projects (option 2)

The VS Tools for Apache Cordova (CTP3) picks up this certificate file on build from a subfolder in the \Users\ directory, and this is what fixed the issue for me...
  1. For CTP3, go to the following directory:

    c:\users\{yourUsername}\.cordova\lib\npm_cache\cordova-windows\3.6.4\package\template\CordovaApp_TemporaryKey.pfx 

  2. Using Visual Studio, create a new Windows Store "Universal App" - this will provide you with an unexpired key file, which will be located in the \BlankShared.Windows subfolder of the project.

    Make a copy of this file:

    BlankSharedAppX_TemporaryKey.pfx 
    ... and rename it to

    CordovaApp_TemporaryKey.pfx
  3. Backup the following PFX file (just in case) and then copy over the newly created PFX file in its place -

    c:\users\{yourUsername}\.cordova\lib\npm_cache\cordova-windows\3.6.4\package\template\CordovaApp_TemporaryKey.pfx

  4. Back in VS, do a build / Clean and then a Rebuild. 
Anyway, that worked for me. Good luck!

Friday, January 9, 2015

Using a "Mac in the Cloud" for Visual Studio Cordova Dev

So you say you want to do iOS development using Visual Studio Tools for Apache Cordova (currently in CTP3)... but you don't actually own a Mac (like me)?

Well there is at least one option: use a "Mac in the Cloud!"

One service that allows "renting" a Mac in the Cloud is aptly named MacInCloud. And, Microsoft has published a nice walkthrough that can help you in getting started:

        Build and Simulate iOS in the Cloud

However, the initial setup can be a bit daunting due to some security and config issues - so I thought I would share my experiences here.

So here are the general steps - 
  1. Register as an iOS Developer

    I just want to mention this step in case you're totally new to iOS development. If you're not yet an iOS Developer, you will need to register and pay the mothership $99 per year. You can get started here.

  2. Get a MacInCloud account with the Remote Build Feature turned on.

    Since I was just dipping my toes into MacInCloud, I wanted to choose the most cost efficient plan, which ended up being their 
    PayAsYouGo plan, which is $1 per hour with a first time purchase of $30 (which covers your first 30 hours). 

    However, I later found out that this plan does not include the Remote Build Feature, which is required for Visual Studio remote deployment and debugging on a Mac. This feature will cost you an additional $5/month.

    If you choose the cheaper PayAsYouGo plan, you will need to contact MacInCloud support (here) to get the Remote Build Feature turned on for your account. (If you go with any of their higher end plans, then remote build will already be enabled). Before contacting support, read #4 below because you'll also want them to ensure vs-mda-remote is installed!

  3. Try Connecting to your Mac in the Cloud

    The MacInCloud service allows RDP access to your rented server in the cloud. Once your account is set up, you will download a series of RDP Configuration files in varying resolutions like so:



  4. Install the Visual Studio Remote Agent

    The Remote Agent (vs-mda-remote) allows Visual Studio to connect to a remote Mac and deploy, build and debug.

    There is a chance that vs-mda-remote will already be installed globally on your Mac server. To check this, open a Terminal window on your Mac and see if vs-mda-remote exists in the global node_modules directory (/usr/local/lib/node_modules/vs-mda-remote) like so:

    First, go to the global node modules dir and list the contents:

            cd /usr/local/lib/node_modules
            ls -l


    ... and if you see a directory named:

            vs-mda-remote

    ... then the VS Remote Agent is already installed on your Mac.

    If vs-mda-remote is NOT found in the global node modules, you can follow the instructions provided in this document: Build and Simulate iOS in the Cloud - HOWEVER, if you went with the PayAsYouGo plan, you will likely hit security issues with Homebrew and Node (which are used to install vs-mda-remote).  So again, it's back to MacInCloud support to help with installing vs-mda-remote.

  5. Do the iOS Developer Dance

    *Sigh* it is a twisted, awkward dance to begin Mac development. In order to allow your Mac In Cloud to develop iOS apps, you need to generate a certificate signing request, and then download the Cert and Provisioning Files from your Mac developer account.

    There are countless docs on how to do this, so I won't repeat all of the steps here but here is an "ok" walkthrough: Generating a certificate signing request

    Once you complete the request, you will be able to download the Certificate and Provisioning Profile from the Apple Dev Center.

  6. Setup XCode with your Dev Account Info

    On your remote Mac, you'll need to give XCode your dev account info. Start XCode from the Applications menu, and then from the system menu for XCode, select Preferences... and then go to the Accounts Tab and enter your apple dev account info:



  7. Start the Remote Agent, vs-mda-remote

    If everything is in place, then we should be able to use Visual Studio on our local machine to deploy and debug on the remote Mac in the cloud!

    Make a note of your Mac's IP Address, which you can get from the terminal window by looking at your shell's prompt (if you don't see it then just type in 
    ifconfig | grep "inet " )

    Next, on the Mac in the cloud, start the vs-mda-remote build agent:

    vs-mda-remote --secure false

    * IMPORTANT! by using secure==false, we are skipping the optional security feature of the server, which forces a Security PIN that changes every 10 minutes. If you are planning on keeping the remote agent running unmonitored for an extended period of time, then you should not do this!

    You should see something like so:

    Copyright (C) 2014 Microsoft Corporation. All rights reserved.
    0.2.5
    Loading resources for language en from /usr/local/lib/node_modules/vs-mda-remote/resources/en/resources.json
    Build Retention initialized with baseBuildDir /Users/userXXXXX/remote-builds/builds, maxBuildsToKeep 20
    Initialized BuildManager with installedCordovaVersion: 4.0.0; baseBuildDir /Users/userXXXX/remote-builds/builds; maxBuildsInQueue 10; deleteBuildsOnShutdown true; allowsEmulate true; nextBuildNumber XXXX
    Remote build Express server listening on [http] port 3000
    ios-sim is installed on path at: /usr/local/lib/node_modules/vs-mda-remote/node_modules/ios-sim/build/release/ios-sim

  8. Deploy and Debug from Visual Studio
    Back on your PC, open up Visual Studio and create or open an existing Apache Cordova App.

    Go to: Tools / Options / Tools for Apache Cordova / Remote Agent Configuration

            Set Enable remote iOS processing to True        Set Host to the IP address of your Mac in the cloud (found in previous step)
            For Security PIN, you can skip this if you started vs-mda-remote with secure false.

    From the Configuration Dropdowns, select Debug / iOS/ and then choose your favorite Simulator



    Now, debug by pressing F5. If there are any errors, you will see them in the VS Output Window (the server side vs-mda-remote has only limited error messaging).

  9. Setting Breakpoints

    I am amazed that setting breakpoints and debugging even works at all given all of the moving pieces here... But yes, there is some flakiness with debugging from VS to vs-mda-remote.

    If you see your breakpoint is not getting hit, first check the VS Output window and look for issues like "resource not found" - which would prevent your breakpoint from even being reached.

    Also there are also cases where a breakpoint is inside some initialization code, and was hit before vs-mda-remote was bootstrapped up. In these cases, you can go to the JavaScript Console inside Visual Studio (visible when debugging) and type in:

    window.location.reload()

Monday, November 24, 2014

Visual Studio Cordova: Black Screen/No Launch

If you are using the Visual Studio Tools for Apache Cordova and your app doesn't launch when debugging, take a look at the Output Windows in Visual Studio for some clues.

Recently I hit a case where the Output Window contained:

              CordovaWebView: TIMEOUT ERROR!

Which means that the app couldn't launch (and the debugger attach) within the allotted time.

You can increase the default launch time by adding an option to config.xml. However, since this option isn't yet supported in the VS Editor for config.xml, you need to edit the XML manually:

  • right-click config.xml and select "Open With..." and then "XML (Text) Editor"
  • below all of the existing <preference> nodes, add the following:

    <preference name="loadUrlTimeoutValue" value="120000" />
...which will increase the load time to 2 minutes.