Wednesday, April 29, 2015

Using Ionic with Visual Studio Tools for Apache 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.

The newly released RC of Visual Studio 2015 Tools for Apache Cordova (VS TACO) makes it easier to create Ionic apps using two different methods.

Method 1: Using the Ionic Templates for TACO

The easiest way (but not the best way) to create a new Ionic project using VS TACO is to use the new Ionic project templates, which are available on the Visual Studio Gallery.

However, there are currently some issues with using the template method:
  • at the time of this writing, the templates do not work with Windows Phone and Windows apps.
  • you are not guaranteed to get the latest Ionic CLI output when using the templates.
  • not all of the Ionic CLI templates are included in the VS Templates.
If any of these are issues for you, then continue to Method 2 below!



Method 2: Importing an Ionic Project

This second method involves creating an Ionic project at the command line, and then importing the source into a VS TACO solution. The advantage of using this method is that you will be sure to have the latest Ionic template source, and you have full control over what you bring into your project.

  1. Be sure you have ionic installed - you can install by typing the following at the command line.

    npm install -g cordova ionic
  2. Now, use Ionic to create a starter project. Ionic supports three different templates: blank, tabs, and sidemenu. To create the tabs template:

    ionic start myApp tabs

    NOTE: instead of tabs in the command above, you can also select blank or sidemenu.
  3. Next, create a Visual Studio 2015 TACO solution using the Blank App template:

  4. From the Visual Studio TACO solution you just created, select the following files and folders:


    ... and copy them to the "myApp" folder that you created using Ionic in Step 2.
  5. Open the myApp.jsproj file from the Ionic folder. Select "Save All" so that a new Solution (.sln) file is created for this project.
  6. Open index.html and add a reference to platformOverrides, which allows dynamic elements to work in Windows and Windows 8 apps:

    <script src="scripts/platformOverrides.js"></script>

    (if you are curious where this file is coming from, look in the merges/windows/scripts subfolder)
  7. At this point, you can run your Ionic app against Android, iOS, and Windows. Go ahead and try it! Note that Ionic does not _fully_ support Windows and Windows Phone platforms, but the Ionic team is working on getting full compatibility with Windows platforms.
  8. For Windows Phone 8.1 support (Windows Phone (Universal)), you will need to make one more tweak: add the following two nodes to config.xml:

    <preference name="windows-target-version" value="8.1" />
    <preference name="windows-phone-target-version" value="8.1" />

Using Crosswalk with Visual Studio Tools for Apache Cordova


4/29/2015 - Updated instructions for Visual Studio 2015 RC


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 is 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

  1. Before you start:

    Download and Expand the Crosswalk 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 Visual Studio 2015 RC. In later versions, these steps might 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. Go to the \platforms\android\CordovaLib subfolder of the project, and delete the contents of \platforms\android\CordovaLib.
  8. Copy AndroidManifest.xml from \platforms\android\ to \res\native\android\
  9. Edit 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. Add a directory named CordovaLib in your \res\native\android\ folder.
  11. The Crosswalk packages you downloaded in Step 1 are needed now.

    copy the entire contents of the ARM directory

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

    to your project's

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

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

    to your project's

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

            \crosswalk-cordova-11.xx.xxx.xx-x86\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. Execute a Build in VS (Ctrl+Shift+B), so that the files in \res\native\android\ are copied to \platforms\android\.  NOTE: At this point, the build will succeed but Crosswalk is NOT yet enabled!
  15. Now we have to build the libs for Crosswalk.

    You only need to do this once.

    Open a command prompt at \platforms\android\CordovaLib and execute:

    android update project --subprojects --path . --target "android-21"

    Next, type in:
    ant debug

    ... you should see a BUILD SUCCESSFUL at the finish.
  16. In the command prompt, go up one directory to \platforms\android\ and once again update the version and run ant:

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

    ... you should see a BUILD SUCCESSFUL at the finish.
  17. Close any of the open cmd prompts and File Explorer Windows, as the VS build process attempts to delete some of these folders.
  18. Back in Visual Studio, select Build/Rebuild Solution. This time your build will take a bit longer because it's packaging up the Chromium runtime with the APK.
  19. Run the project on the device using F5. Note that Visual Studio currently does not support debugging with Crosswalk, because it cannot attach it's debugger. You can use ChromeDev tools to debug, however.
  20. 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 40.0.2214.91, but it depends on the release of the Crosswalk libraries you downloaded in Step 1):




    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!

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.


Friday, January 30, 2015

Thursday, January 29, 2015

Using Crosswalk with Visual Studio Tools for Apache Cordova


UPDATE 4/29/2015: For Visual Studio 2015 RC, please see this updated post!

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


UPDATE 4/29/2015: See this updated post for Visual Studio 2015 RC! (Below is for CTP3)

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...