Bindable Application Bar (Attached Property) – Windows Phone 7

In a prior blog post I had created a Blend Behavior for creating a bindable ApplicationBar. The problem with the Blend Behavior is it seems to have a static instance that then attaches to multiple objects. It’s very confusing to me and I need to do a lot more research on Blend Behaviors. The result has been the creation of a BindableApplicationBar attached property.

I was able to repurpose the code I had written for the Blend Behavior. The new attached property is very simple. It has a collection of ApplicationBarIconButtonDelegate objects and a collection of ApplicationBarMenuItemDelegate objects. Long names I know, I’ll work on shortening those up. As soon as the BindableApplicationBar’s DataContext is set each button delegate’s and menu item delegate’s DataContext is set as well. At this point bindings kick in and based on visibility the BindableApplicationBar adds the delegates’ ApplicationBarIconButton or ApplicationBarMenuItem objects to the correct collections on the actual ApplicationBar. Confused? Let’s show some code.

Hooking up the attached property looks like this:

<Code:BindableApplicationBar.BindableApplicationBar>
	<Code:BindableApplicationBar>
		<!--NOTE: The ability to add more than 4 buttons and change their state based on binding.
				If they are visible then they are added to the app bar, otherwise they are removed from the app bar.
			IMPORTANT: Always change the visibilty of the buttons in the app bar before those not in the app bar
				and avoid having 2 buttons bound to the same property for visibility-->
		<Code:BindableApplicationBar.ButtonDelegates>
			<Code:ApplicationBarIconButtonDelegate IconUri="/Images/appbar_button1.png"
													Text="{Binding TextCommandHeader}"
													Command="{Binding ChangeTextCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Increase"
													Command="{Binding ChangeNumberCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Toggle"
													IsVisible="{Binding CanToggleCanChangeNumber}"
													Command="{Binding ToggleCanChangeNumberCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Hide"
													IsVisible="{Binding CanHide}"
													Command="{Binding HideToggleCommand}" />
			<Code:ApplicationBarIconButtonDelegate Text="Show"
													IsVisible="{Binding CanShow}"
													Command="{Binding ShowToggleCommand}" />
		</Code:BindableApplicationBar.ButtonDelegates>
		<Code:BindableApplicationBar.MenuItemDelegates>
			<Code:ApplicationBarMenuItemDelegate Text="Random Number Text"
													Command="{Binding ChangeTextMenuCommand}" />
		</Code:BindableApplicationBar.MenuItemDelegates>
	</Code:BindableApplicationBar>
</Code:BindableApplicationBar.BindableApplicationBar>

Once the DataContext of the BindableApplicationBar and all delegate objects are set this code gets run:

private void Initialize(object dataContext)
{
	if (DataContext == dataContext)
	{
		return;
	}

	DataContext = dataContext;

	foreach (var buttonDelegate in ButtonDelegates)
	{
		buttonDelegate.DataContext = DataContext;
		if (buttonDelegate.IsVisible)
		{
			AddAppBarButton(buttonDelegate.Button);
		}
		buttonDelegate.IsVisibleChanged += AppBarButtonIsVisibleChangedHandler;
	}

	foreach (var menuItemDelegate in MenuItemDelegates)
	{
		menuItemDelegate.DataContext = DataContext;
		if (menuItemDelegate.IsVisible)
		{
			AddAppBarMenuItem(menuItemDelegate.MenuItem);
		}
		menuItemDelegate.IsVisibleChanged += AppBarMenuItemIsVisibleChangedHandler;
	}

	UpdateAppBarVisibility();
}

Something that I CANNOT find anywhere, which then became my motivation for writing my own BindableApplicationBar was the ability to have Visibility of the buttons and menu items bound as well as IsEnabled. I added an IsVisible property that drives whether or not the button or menu item is added to the ApplicationBar. Super simple. Also, the delegate objects subscribe to their object’s click event. So one could using Commands and binding, click handlers, or both just like on a normal button.

ApplicationBar.Opacity Fact

Here is an interesting fact for you. The property ApplicationBar.Opacity is 1.0D by default. What I recently learned is that the ApplicationBar.Height is 72px and if Opacity is 1 then the ApplicationBar actually takes up space in the layout of the page. However, as soon as the Opacity is .999D or not equal to 1 then the ApplicationBar no longer participates in the layout of the page. This was a pretty big bummer to the project I’m on since we need to manage our ApplicationBar quite a bit. Wait animations were starting in one spot then moving down after the ApplicationBar would hide. It was very confusing why this was happening until I read about this behavior in the documentation.

So what does all that have to do with the BindableApplicationBar here? Opacity by default is now .999D in order to have a consistent feel across the app. Why .999 not just .9? If .9 is used the ApplicationBar is noticeably transparent, however .999 looks completely Opaque.

Known Issues

The biggest issue I’m aware of right now is the possibility to try and add more than 4 ApplicationBarIconButtons to the ApplicationBar. If the developer adds 5+ button delegates they need to be very careful about managing the visibility of the buttons. Only 4 buttons can be added at a time. The 5th will throw an exception. I’m working on a solution for this, but for now the current version works well enough.

Another nice to have would be the ability to specify permanent order. Currently if 4 buttons are visible and the first is removed (visibility change) and later is readded it will now be the last button. The solution I’m toying with for the above issue would also allow me to fix this one fairly easy as well.

The last major known issue is that DataContext must be set. This means that if the page does not have a DataContext then the the BindableApplicationBar.DataContext property should be set to a string such as BindableApplicationBar.DataContext=”a”. This will cause the logic in Iinitialize(object dataContext) to run (found above).

Sample Code

Finally, the stuff everyone really cares about. Feel free to do whatever you want with the code. I’d love to hear if you’re using it and any feedback you have about the code. Hopefully this is helpful.

BindableApplicationBar Sample Code

Microsoft Surface – Installing an App on V2

Previously, I wrote about porting my Surface Craps application from Surface v1 to v2.  Now that the app has been upgraded, here’s a short post on how to update the installer to work with v2.

There is not much different about the makeup of an application that is registered on the Surface between v1 and v2.  Your program binaries go in a directory, and then (new to v2) a SHORTCUT points the Surface shell to that directory.

Program Files

Unlike v1 that required you to install your program files in a specific “Program Data” sub directory, now you can install your program files to a directory of your choice – usually %ProgramFiles(x86)%.

CropperCapture113

Program Data Shortcut

Next, make your installer create a SHORTCUT to the directory where you install your program files, and place the shortcut in the Surface v2 directory:  C:\ProgramData\Microsoft\Surface\v2.0\Programs.

It’s important that this shortcut is to the DIRECTORY where your program files are, not a shortcut directly to the application .xml file.

Here’s how the Surface programs directory and shortcut properties should look.

CropperCapture115

That’s it – you should now see your application in the chooser when you run the shell.

Have a Nice Conflict

“IN THE STORY that follows, we explore the practical ideas of relationship awareness theory.”
From the book
Have a Nice Conflict

When I read that first sentence from “Have a Nice Conflict” I said to myself, “God, I am going to hate this book.”  I’m an engineer by trade.  I have a black and white personality.  Let me come clean on the truth: My book reading (and writing for that matter) for the last decade has been limited to mostly software and fly fishing.  Don’t get me wrong.  It’s my job to read.  A huge portion of my day is spent reading.  But, the sheer thought of reading a management self help book made me cringe.  I have tried to read books like this, but I never finish.

This book “Have a nice Conflict” is climbing the Amazon and NY Times Best seller list.  And now that I have read the book, I can see why. Have a Nice Conflict

From where I write this in my office I can clearly see the books, “Execution”, “Never Eat Alone”, “The Five Dysfunctions of a Team”, and “How Full is your Bucket” among other self help business books in my bookcase.  And I look back at all those like it was a waste of my time to read them.  It’s not that they are not valuable, I know they are very valuable for many people.  They just didn’t feel like reading them was a good spend of my time – Again the weakness / arrogance of my black and white personality.  Well, that, and to be frank, turning turning obvious concepts into books seems like such a waste of trees.

But, the engineer is an interesting breed.  As any PM will tell you they are very hard to manage.  Why?  Well I disdain generalizing any group of humans, but where in the world do we find a group of such arrogant “I’m the smartest person I have ever met and not only do I know everything about engineering I know everything about everything.” and at the same time have such fragile egos that need to be constantly appreciated than engineers?  This group is rife with conflict.  And I’m one of them I fear.  And it’s not like I wasn’t aware of it until reading the book.  I was.  But, the biggest lesson I learned from reading the book is that as a “Red”, I leave a huge calamity of conflict in my wake…and I don’t even realize it.  The book has helped to explain why I am so puzzled at some people’s reactions to the “matter of fact” things I say.  You’ll have to read the book to figure out what a “Red” is and all the other colors of humans that the book classifies.

If you are an engineer or have to work with them directly, I strongly recommend you get your hands on this book.  It’s premise is preventing, managing and leveraging conflict.  But, it is the details around the story told that pulls it together for “black and whites” like me.

Presentation Materials for NEVB User Group February

Thanks to everyone for coming and all the questions! It was great to get to introduce some more people to Windows 8 along the way too.

Downloads for Previews and CTPs can be found here: http://msdn.microsoft.com/en-us/vstudio/async.aspx

Slides: Async 2012

Async Sample: Demo Code for VS 11 (VB) | Demo Code for VS 11 (C#) | Demo Code for Async CTP in VS 2010 (C#)

Metro Sample: Code for VS 11 (C#) Requires Windows 8 to open in VS

Multi-app support on a single Windows Phone 7 push notifications server

Windows Phone 7 push notifications are tricky. Take Microsoft’s clear-as-mudd “overview” diagram, for example…

Notifications Diagram

All sorts of colors and arrows going on there. The green parts represent code that you write, and the blue parts represent what Microsoft already has in place. The numbers and arrows represent the awkward dance between them. I’ll try to explain…

First, in your application (green side of step 1) you have to use Microsoft’s client side portion of their Push Notification Service, which is the HTTPNotificationChannel class (blue side of step 1) , to see if the app already has an open notification channel with Microsoft’s service (that’s the MPNS box in the bottom right). Only one channel per application is allowed, and you can use that single channel for all of your apps Push Notification needs.

If there is no channel open already, you can go ahead and use the aforementioned HTTPNotificationChannel class to set one up. This is step 2 in the diagram above, and here is a sample of it in code….

*I used this tutorial by Ben Cull for most of the code you’re going to see, until we get to the “multi-app” support on the server.

private void RegisterDevice()
		{
			HttpNotificationChannel httpChannel;
			httpChannel = HttpNotificationChannel.Find("TestChannel");

			if (httpChannel != null)
			{
				SubscribeToChannelEvents();
				SubscribeToService();
			}
			else
			{
				httpChannel = new HttpNotificationChannel("TestChannel", "TestService");
				SubscribeToChannelEvents();
				httpChannel.Open();
				if (!httpChannel.IsShellToastBound)
				{
					httpChannel.BindToShellToast();
				}
				if (!httpChannel.IsShellTileBound)
				{
					var c = new System.Collections.ObjectModel.Collection<Uri>();
					c.Add(new Uri("http://0.tqn.com/"));
					httpChannel.BindToShellTile(c);
				}
			}
		}

The call to the “SubscribeToChannelEvents()” method above is represented by step 3 in the diagram, and here’s what it looks like in code…

private void SubscribeToChannelEvents()
		{
			httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
			httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived);
			httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
			httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred);
		}

Step 4 in the diagram is sending your notification channel’s URI (it gets this URI through magic during step 2). This is where you need to have a WCF REST Service set up with a database to hold your device id’s and URI’s. The code below shows how to subscribe to the service from the client side, but if you want the server side setup and registration you can find all of that in Ben Cull’s blog post here

public string ParseANID(string anid)
		{
			if (!String.IsNullOrEmpty(anid))
			{
				string[] parts = anid.Split('&');
				IEnumerable<string[]> pairs = parts.Select(part => part.Split('='));
				string id = pairs.Where(pair => pair.Length == 2 && pair[0] == "A").Select(pair => pair[1]).FirstOrDefault();
				return id; } return String.Empty;
		}

		private void SubscribeToService()
		{
			if (!NetworkInterface.GetIsNetworkAvailable())
			{
				return;
			}

			string id = ParseANID(UserExtendedProperties.GetValue("ANID") as string);
			var emulatorUrl = string.Format("http://localhost:55875/notifications/register?deviceid={0}&uri={1}", id, httpChannel.ChannelUri.ToString());
			var wc = new WebClient();
			wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
			wc.DownloadStringAsync(new Uri(emulatorUrl));
		}

The “ANID” that you see above is pretty much a unique guid generated for each user’s Live ID. Also, the emulatorUrl variable above is assuming that you’re running the WCF service on the same machine that you’re writing the client side phone code on, and that you’re using the phone emulator to debug. If you’re using an actual device to debug than “localhost” will produce nothing but disappointment, so adjust your url as needed. At this point, if you followed the WCF REST Service tutorial i linked to above, you’ll have the infrastructure in place to send push notifications, but no actual way of doing so yet.

For that we’ll need a service running on the server, with a timer that goes out and determines if there’s any updates it needs to send to anyone (for example, a weather service that checks for severe weather wvery 30 minutes based on a zip code sent by the client side phone app). But all of this is for a single app. If I wanted to do push notifications again in the future i would have to do this all over again for each new app. Instead, I decided to use a single REST Service, web service, and central device database. The service doesn’t contain the timer with the application logic. Instead, each app that you want to support is represented by a class that you instantiate in the OnStart() method of the service, and each app class contains its own timer, logic, and its own database with device id’s and any parameters required for it to work. For the sake of simplicity below are 2 examples of test apps that use the AppName property of the central database rather than their own seperate databases….


namespace PushNotificationService.Apps
{
	public class TestApp
	{
		private WP7AppDBEntities _dbContext;
		private readonly string _appName = "TestApp";

		public TestApp()
		{
			_dbContext = new WP7AppDBEntities();
			var t = new Timer();
			t.Interval = 10000;
			t.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
			t.Start();

		}

		private void OnTimerElapsed(object sender, ElapsedEventArgs e)
		{
			_dbContext.Devices.Where(d => d.AppName == _appName).ToList().ForEach(d =>
			                                                                      	{
			                                                                      		try
			                                                                      		{
			                                                                      			PushNotifications.SendToast(d.URI, "Test",
			                                                                      			                            "Hello");
			                                                                      		}
																						catch{}
			                                                                      	});
		}
	}
}

namespace PushNotificationService.Apps
{
	public class TestApp2
	{
		private WP7AppDBEntities _dbContext;
		private readonly string _appName = "TestApp2";

		public TestApp2()
		{
			_dbContext = new WP7AppDBEntities();
			var t = new Timer();
			t.Interval = 20000;
			t.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
			t.Start();

		}

		private void OnTimerElapsed(object sender, ElapsedEventArgs e)
		{
			_dbContext.Devices.Where(d => d.AppName == _appName).ToList().ForEach(d =>
			                                                                      	{
			                                                                      		try
			                                                                      		{
			                                                                      			PushNotifications.SendToast(d.URI,
			                                                                      			                            "TestApp2!",
			                                                                      			                            "It's working!");
			                                                                      		}
																						catch{}
			                                                                      	});
		}
	}
}

The PushNotifications.SendToast method that you see above represents step 5 of the diagram, and is provided in detail here.

And here are the classes being instantiated in the OnStart() method of the service…

protected override void OnStart(string[] args)
		{
			var testApp = new TestApp();
			var testApp2 = new TestApp2();

		}

Windows Live SDK for Windows Phone 7 – SoCal Code Camp Presentation (1/28/2012)

This was my first time presenting at any code camp. I’d like to thank those that attended and participated. They made the experience very enjoyable. You can download my slide deck here. I hope you find the information useful. Please let me know if you need any links that are not included in the slide deck.

Summary

Interest in the Windows Phone 7 platform is growing quickly and the need for apps is increasing faster still. However, not everything related to a consumer’s Live profile is available on the phone natively. On Dec. 7, 2011 Microsoft released a new Windows Live SDK which allows access to Calendars, Contacts, Documents, and more. We’ll be walking through the SDK and learn how to implement calls to Windows Live in order to support the rich functionality desired by consumers of Windows Phone 7.

Cheers and Happy Coding!

Presentation Materials for Fullerton Code Camp 2012

Additional downloads to try out the demo code:

Download the Visual Studio 11 Developer Preview: http://msdn.microsoft.com/en-US/vstudio/hh127353

Or get the Async CTP for 4.0 and Visual Studio 2010: http://msdn.microsoft.com/en-us/vstudio/async.aspx

Windows 8 Developer Preview for all WinRT/Metro samples: http://msdn.microsoft.com/en-us/windows/apps/br229516

Easy Async with .NET 4.5: Slides

Code: .NET 4.5 Code (requires VS11 Preview) | Same Code for .NET 4 CTP

Windows 8 Metro Code (requires VS 11 on Windows 8 to build)

The Future of XAML: Slides

Code: Sample Metro App (requires VS 11 on Windows 8 to build) | Sample Silverlight 5 App (shows some things that either don’t work or change in Metro)

How to use PhoneGap to port quickly your web app to a native iOS and Android device

This blog post will show how to take a web site written only in HTML5, CSS3 and JavaScript and quickly develop an iOS and Android mobile application. In order to do this, I will use Adobe PhoneGap, a mobile web frame to build cross-platform mobile applications. As mentioned in my previous blog post, PhoneGap is an HTML5 app platform that allows you to author native applications with web technologies. Even though my blog post will only show how to develop an iOS and Android application, PhoneGap also supports developing BlackBerry, webOS, Windows Phone 7, Palm devices, etc. In a nutshell, you’ll be using a PhoneGap wrapper that contains your web-based HTML, CSS and JavaScript code. Also, you will gain access to many of the device’s native features such as the compass, camera, the contacts list, accelerometer, etc.

PhoneGap introduced last year PhoneGap Build which offers a cloud-based service that takes your app written in HTML5, CSSe and Javascript and sends you back app-store ready apps for iOS, Android, Palm, Symbian and the other mobile platforms. Check out pricing and other details on their web site.

Below is a general process involved in getting setup using PhoneGap and developing an application:

1. PhoneGap has a great Getting Started tutorial for all the mobile platforms. Download the PhoneGap tools and the specific set of tools for the platforms you’re working with. For example, download Xcode and iOS SDK if you plan on porting your web site to an iOS application. Download the Android SDK and Eclipse if you plan on making an Android application.

2. Install all the platform tools and PhoneGap to your existing environment.

3. Start developing your web application and test with a web browser of your choice. I normally use Visual Studio to write my web application and test it using Safari, Chrome or any webkit supported browser. Since these are the types of browsers on smartphones. I would take advantage of Visual Studio’s IDE in debugging my javascript code or Web Inspector in Safari or the dev tools found in FireFox or Chrome.

4. Once you’re ready to port it to a mobile application, you will put all your web files within the www folder. For Xcode, all you need to do is create a new project using the PhoneGap template. Once the project is created, immediately compile the project. Once the project is done building, a www folder will be created in your project folder. Add the www folder into the project navigator. This is where you will house all your web files (HTML5, CSS3 and Javascript files). Run your project and you should see your web page displayed in the iPhone or iPad simulator.

5. For Android, install Android SDK, Eclipse and then the Android plug-in for Eclipse. Create an Android project in Eclipse and follow these steps to modify the project to support PhoneGap. Then run the project and select an Android Virtual Device (AVD) to use as the emulator to display your application.

6. Steps 4 and 5 can be done for you using PhoneGap Build. Just upload your web application files using their Cloud service and they will send you back app-store ready packaged files for the mobile platforms they support.

7. A noteworthy caveat is you will have to tweak some of your web language code depending on which mobile platform you choose. Not all mobile devices are similar in hardware but PhoneGap does an excellent job in pointing out issues through their API Docs section on their web site.

For step 5, here are some links to great tutorials on how to Get Started in developing for Android:
1. Getting Started With Android Development Using Eclipse
2. Getting Started with Android on a Mac
3. Running Android SDK Examples Using Eclipse

So below is a web page example written only in HTML5, CSS3 and Javascript. The HTML consists of an input element and a button. Using JavaScript, it dynamically shows in an unordered list the input values you submit. If you click any of the list items in the unordered list, it will make a call using the Twitter Search API and return the latest tweet with that keyword as an input parameter.

HTML elements:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    <body>
	<div id="main">
        <h1>Search Twitter</h1>
        <form id="foodForm">
            <input type="text" id="foodName" placeholder="keyword" />
            <button id="submitFood">Tell Us!</button><br>
        </form>
        <ul id="foodList">
        </ul>
        </div>
   </body>
}

JavaScript code event handler when DOM is loaded:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    document.addEventListener("DOMContentLoaded", function () {
            //navigator.notification.alert("I think today will be a great day.", function() {}, "Great Day");
            // uncomment below code to clear items in LocalStorage
            //window.localStorage.clear();
            // <ul> instance variable
            var foodList = document.getElementById('foodList');
            // textbox instance variable
            var foodField = document.getElementById('foodName');

            // length of food items in localStorage
            var l = window.localStorage.length;
            var i = 0;
            var storedFoodName;

            // add food item to <li> child
            function addNewFoodItem(foodName) {
                var newFoodItem = document.createElement('li');
                newFoodItem.innerHTML = foodName;
                foodList.appendChild(newFoodItem);
            }

            // loops through localStorage for food items and calls addNewFoodItem function
            for (i; i < l; i++) {
                storedFoodName = window.localStorage.key(i);
                if (storedFoodName.match(/^food[.]/))
                    addNewFoodItem(window.localStorage.getItem(storedFoodName));
            }
}

Javascript code that gets handled when the button is clicked:

document.getElementById('foodForm').addEventListener('submit', function (evt) {
                evt.preventDefault();
                var newFood = foodField.value;

                // creates a foodKey value with food.[length]
                var foodKey = "food." + (window.localStorage.length + 1);
                // calls addNewFoodItem function
                addNewFoodItem(newFood);
                // saves foodKey and input food to localStorage
                window.localStorage.setItem(foodKey, newFood);

                // clears foodFied variable
                foodField.value = "";
                return false;

            }, false);
        });

Javascript code that calls the Twitter Search API remote service using the XMLHttpRequest object and parses the JSON data returned. It displays the latest tweet in a notification alert after you click on the ListItem in the unordered list.

// callback function to get the latest tweet
        function getLatestResult(JSONstring) {
            var twitterPayload = JSON.parse(JSONstring);
            var latestResult = twitterPayload.results[0];

            return latestResult;
        }

        // performs a get request for url
        // passes the response text to callback
        function getXHR(url, callback) {
            var req = new XMLHttpRequest();
            req.onreadystatechange = function () {
                if (this.readyState == 4) {
                    if (this.status == 200 || this.status == 0) {
                        callback(this.responseText);
                    } else {
                        console.log('something went wrong');
                    }
                }
            }
            req.open('GET', url, true);
            req.send();
        }

        // event handler for the clicks on <li> elements using event delegation to catch all of these events.
        // We listen on the document element, and then, if the target of the event matches one of our list items,
        // fires the event handler
        document.addEventListener("click", function (evt) {
            if (evt.target.tagName == 'LI') {
                // gets the selected <li> element
                var foodSubject = evt.target.innerHTML;
                var foodSearch = encodeURIComponent(foodSubject);
                // generates twitterURL for Twitter Search API
                var twitterUrl = 'http://search.twitter.com/search.json?q=' + foodSearch;

                // calls getXHR function to get latest tweet of selected <li> element
                // then calls callback function to pop-up an alert msg with latest tweet
                getXHR(twitterUrl, function (response) {
                    var latestTweet = getLatestResult(response);
                    var msg = 'Latest Tweet about ' + foodSubject + ' from ' + latestTweet.from_user + ': ' + latestTweet.text;
                    //navigator.notification.alert("PhoneGap is working")
                    alert(msg);
                })
            }

        }, false);

Project Navigator in Xcode

Project Navigator in Xcode for PhoneGap project

iPhone Simulator of Search Twitter

iPhone emulator of PhoneGap application

Project Explorer in Eclipse

Project Explorer of Android project in Eclipse. Notice the /assets/www folder and /libs folder with PhoneGap related web files

Android Virtual Device

Android Virtual Device running the web page

PhoneGap is good at helping developers leverage their experience at building web applications using web standards, HTML, CSS and JavaScript. If you know web standards, you’ll experience few problems while working with PhoneGap. All you need to learn is how to use the PhoneGap API. Once you become familiar with the PhoneGap API, you can quickly take advantage of accessing the device’s camera, pull up the contacts or work with the accelerometer or compass.

As the web site example above shows, if you need to connect your application with a remote web service, you can easily bring in tools like jQuery to create powerful Ajax handlers. Or as I demonstrate in how to use XmlHttpRequest objects.

As I pointed out in step 7 above, just because you code a web application using PhoneGap and it works on an iPhone device, it doesn’t automatically mean that it will work on other devices. You will have to test and tweak for the other devices that are supported.

If you want to port to multiple devices, you will need separate environments for each wrapper. For example, you won’t be able to maintain your Android PhoneGap wrapper with Xcode. I used my Mac and have installed Xcode and Eclipse but I make sure I keep them in separate environments.

Microsoft Surface – Porting from v1 to v2

A couple years ago, I wrote Surface Craps during RECESS to explore the Microsoft Surface table and APIs.  Now that Surface 2 is out, it’s time to upgrade the software to run on the new hardware.  This is the first in a series of blog posts about the process in upgrading from Surface v1 to v2.

Obviously this first requires that you have the Surface 2 SDK installed.  To start, I branched the project tree in TFS to make a v2 copy.

Open the project in VS 2010.  Update the project references.  The new referenced assemblies are in C:\Program Files (x86)\Microsoft SDKs\Surface\v2.0\Reference Assemblies.

  • Microsoft.Surface.dll
  • Microsoft.Surface.Presentation.dll
  • Microsoft.Surface.Presentation.Generic.dll

I was using Visual State Manager from the WPF Toolkit, and now it’s included in WPF 4, so I removed that reference as well.

Now we start the brute force process of fixing code that doesn’t compile.  Here’s a list of what I found.  Many of these changes are moving to WPF 4 in general, since it’s where we get most of the touch functionality in the Surface 2 environment.

Control Name Changes

Surface v1 Surface v2
SurfaceUserControl UserControl
SurfaceContentControl ContentControl

Event Handling Changes

Surface v1 Surface v2
ContactDown event use TouchDown
(Preview)ContactUp/Down use (Preview)TouchUp/Down
ContactDown event use TouchDown
(Preview)ContactUp/Down (Preview)TouchUp/Down
ContactChanged TouchMove
ContactEventHandler EventHandler<TouchEventArgs>
ApplicationActivated, etc. OnWindowInteractive, Noninteractive, Unavailable (see a default new Surface 2 project for an example of these event handlers)
ApplicationLauncher.Orientation ApplicationServices.InitialOrientation

Property / Method Changes

Surface v1 Surface v2
e.Contact.IsTagRecognized e.TouchDevice.GetIsTagRecognized( ). (add using statement for Microsoft.Surface.Presentation.Input to get the extension method)
e.Contact.Tag.Byte.Value e.TouchDevice.GetTagData().Series & .Value
e.Contact.GetPosition( ) e.TouchDevice.GetPosition( )
e.Contact.GetOrientation( ) e.TouchDevice.GetOrientation( )
ScatterViewItem.IsActive ScatterViewItem.IsContainerActive

Manipulation Processing

In Surface v1, you would use the Affine2DManipulationProcessor to handle gestures such as flick, rotation, scale, etc.  In v2, you just use the manipulation processing that’s provided by the WPF 4 UIElement.

Surface v1 Surface v2
On any elements that you want to track manipulations on, set IsManipuliationEnabled = true
BeginTrack( ) nothing to do in v2
Affine2DManipulationCompleted, … events UIElement.ManipulationCompleted, … events
e.Velocity.Length e.FinalVelocities.LinearVelocity.Length
e.TotalTranslation.X e.TotalManipulation.Translation.X

Resolution

That’s all I had to as far as API differences.  Next came the resolution differences. The Surface v2 display runs at 1920 x 1080, so if you have any UI that does not stretch or any hardcoded coordinate-based math in your software, it will have to be updated.

Tags

Surface v2 does not support Identity tags, but it does support Byte tags.  See the tag-related methods above for the API differences.

For Surface Craps specifically, I ran into a problem with the transparent dice we got from Microsoft for Surface v1. The dice have byte tags on them that are practically transparent, but have enough IR reflectivity to be picked up by the Surface v1 infrared cameras.  In Surface v2, the tags are recognized by interpreting the contact information using PixelSense technology, and something in that processing is not recognizing the mostly transparent tags on the dice.  I will continue to investigate this issue and write another post if I have any update.  For now – it’s a bummer that the physical dice do not work.

Installation

In a future post I will talk about the differences in what it takes to install your application in Surface v2…

 
 
 

PhoneGap, Appcelerator and mobile web frameworks

What are mobile web frameworks

What are web based application frameworks? First, there are many out there including PhoneGap, Appcelerator, etc. For developers struggling to learn Objective-C, Java, etc these frameworks allow you to still build mobile applications. Essentially, these frameworks exist to help developers that come from a web development background with a set of tools to use with their current skillset (HTML, CSS and Javascript) to build native or native-like mobile applications. PhoneGap and Appcelerator Titanium are the most popular amongst all the frameworks out there on the interweb. For this blog post, I want to compare and contrast the two along with other mobile frameworks. Hopefully this will help you if you’re deciding on which framework to architect your next project.

PhoneGap is developed by Nitobi Software which was recently acquired by Adobe. On their website, it says “Build apps in HTML and Javascript and still take advantage of core features in iPhone/iPod touch, iPad, Google Android, Palm, Symbian and Blackberry SDKs.” Currently, PhoneGap v1.3 supports 7 different platforms including iOS, Android, Palm, WebOS, WP7, Symbian and Bada. The framework is open source which means developers and companies can use PhoneGap for mobile applications that are free, commercial, open source, or any combination of these.

What is required to use PhoneGap

PhoneGap projects require the underlying SDKs (e.g. iOS 5 SDK) to be installed and building the project happens from an IDE, such as Xcode 4. Once you have Xcode and iOS 5 SDK installed, download PhoneGap and install it. Open up Xcode and under the New Project dialog, there should be a PhoneGap-based Application project template as shown in Figure 1.

New Project Dialog

Figure 1

After installing the PhoneGap project template, make sure to build and launch the iPhone simulator. You should see an error in your simulator informing your “index.html” was not found as shown in Figure 2.

iPhone Simulator Error

Figure 2

In order to fix this, go ahead and copy the ‘www’ directory to the Project Navigator in Xcode. The ‘www’ folder exists in the PhoneGap project folder location. You can quickly go to that folder by right-clicking on the project root in Project Navigator and selecting “Show In Finder”. After you drag the ‘www’ folder, you should see a prompt as shown in Figure 3. Select “Create folder references for any added folders” and click Finish.

Folder Reference

Figure 3

Your Project Navigator should look similar to Figure 4.

Project Navigator

Figure 4

Now rebuilt and run the iPhone simulator again and you should see similar to Figure 5

iPhone Simulator

Figure 5

Basically, the developer puts his files (HTML, CSS or Javascript) into a ‘www’ folder in the project directory. When building, PhoneGap then renders these files inside a native WebView provided by the OS-specific language (either Objective-C or Java), it exposes access to certain native device features, like Accelerometer, Camera, Notifications, etc.

In a nutshell, a PhoneGap application is essentially still a web application, wrapped inside a WebView. It still remains a web application that is displayed through rendering of HTML, CSS and Javascript using a browser instance on a mobile device.

Appcelerator Titanium

Appcelerator Titanium is another mobile framework to help developers build mobile applications but only on iOS and Android at this time. Similar to PhoneGap, Titanium provides a binding layer that maps Javascript function calls to natively available APIs.

However, Appcelerator claims to be different than PhoneGap in translating Javascript code to native application code. The Javascript code is being interpreted during runtime and through a bridge layer, function calls to Titanium.some_function invoke native application code under the hood.

Another way Appcelerator is different is up until the latest version of Appcelerator, v1.5, you would write your application code in HTML, CSS and Javascript. Now, the application code is written in pure Javascript, using mainly functions that the Titanium API exposes. Apart from using it to access special device features (Camera, Accelerometer, etc), it also enables the developer to render native UI elements (buttons, tables, etc).

These differences give Appcelerator an edge of performance. Just want to emphasize, all the application code will be in Javascript, even the styling of elements happens through function calls. One thing to also keep in mind is to ask yourself will the Javascript API provide all the functionality needed in your application.

Unlike PhoneGap, building and packaging your application does not happen inside an IDE (Xcode, Eclipse, etc), but through their software, Titanium Developer. This is the tool to set up new projects, configure, test and package them. Any IDE of your choice can be used to write the application code.

When choosing a mobile web framework, keep in mind it depends on the requirements of the application when choosing which framework to go with. If the goal is to target many platforms as possible, then PhoneGap may be the right choice. If true native-ness and performance is important, then Titanium may be the choice.

There are many other mobile web frameworks out there that are open source and free and some that charge a developers license fee. I would like to write a follow up blog post on MonoTouch, NimbleKit, AppMobie and others. Stay tuned.