This turned out to be fairly trivial thanks to Xamarin and two components in their Component Store:
JsBridge - eases Native to Javascript communication
ZXing.Net.Mobile - handles the barcode scanning
Here are some screenshots of what the web app looks like when accessed via the iOS app:
One of the requirements of the bar code scanning was to not show the Scan button if the user is not using the native app. To do this I customize the UserAgent of the UIWebView and then do UserAgent sniffing on the server side to hide or show the Scan button.
http://xamarinbarcodesample.apphb.com/
To enable this functionality in the iOS app we append a XamarinBarcodeSampleApp string to the default UserAgent of the UIWebView:
Then in the web app we do UserAgent sniffing for this string.
To wire up the Scan button we take advantage of JsBridge. The first thing we do is register the mt.js library. Secondly we listen for the scanComplete event which is triggered on the iOS app side. Thirdly we handle the Scan button click event and let the iOS side know about it by firing the scanBarcode event.
On the iOS side we need to enable JsBridge, then listen for the scanBarcode event. When scanBarcode is fired we display the ZXing.Net.Mobile scanner. If the user successfully scans a barcode we fire the scanComplete event and pass the barcode string as an event parameter.
The native / hybrid iOS app source code can be downloaded here:
https://github.com/crdeutsch/Xamarin.iOS.BarcodeSample
The web app source code is here:
https://github.com/crdeutsch/Xamarin.Web.BarcodeSample
Final thoughts:
Xamarin tools are flexible enough to handle the requirements of the Web Application developer dipping their toes into native development.In fact the Xamarin tools work so nicely with UIWebView based web apps that I'd urge any developer looking at PhoneGap or Titanium to add Xamarin to your review list and avoid the limitations you may run into.
For instance, I built a series of HTML5 based game for a client that play audio via Flash in a desktop browser. To make them work on an iPad I used Titanium to martial the audio playback to native code. At the time I figured Titanium was the best solution since the bulk of the code was already Javascript. I eventually ran into limitations with Titanium when I wanted to detect custom gestures and realized they don't have a 1 to 1 mapping with the iOS API like Xamarin does. I plan on porting this app to Xamarin in the near future to take advantage of more advanced native iOS functionality.
In a future blog post I will demonstrate how to use JsBridge and another library I wrote to martial audio calls to the native side like I did for those HTML5 games.
DISCLAIMER: I've been work full time for Xamarin for about 3 weeks as a web developer. The following experiences and opinions were developed during my 3 years as a freelance consultant.