jQuery Mobile and AngularJS Working Together

Both jQuery Mobile (jQM) and AngularJS are awesome at what they do, but getting them to play nicely together can be tricky.  As you may have discovered, both want to manipulate the URL/routes and DOM such that it’s very easily to get them in conflict.  Having been through this recently, I wanted to share some recommendations to get them working together:

Load jQM libs before AngularJS

Because both frameworks heavily manipulate the DOM, it’s important to get the load order right.  I found that loading AngularJS first led to some interesting (and annoying!) UI functionality.  The correct order should be jQuery first, followed by jQM, and then AngularJS:

<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular-resource.min.js"></script>

Let jQM handle the URL routing

I’m likely to get flamed for this by MV* purists, but I recommend letting jQM handle all of the URL routing – and not using AngularJS for any routing.  Firstly, I spent a lot of time trying it the other way (disabling routing for jQM, and configuring various routes, templates, partial files, etc.).  Even when it did work, it was just a mess – it looked like someone had taken a shotgun to my jQM app and blown it into several pieces.  Secondly, I would argue that URL routing really shouldn’t be a primary consideration for a mobile Web app.  The app is more likely launched by an icon on the home screen vs. a search or link with any type of query string.  Even if it does, a simple check for a null scope is all that’s required.

Create a single Angular controller for a group of jQM pages

Conforming to #2 means that you can create a single controller that spans a number of individual jQM pages.  This usage results in very elegant single HTML page together with a single controller – yet has the advantage of offering multiple pages to the user.

To demonstrate this in more detail, and because you can’t have enough Todo list apps, I’ve put together a sample using jQM, AngularJS, speaking to a service using Node, Mongoose, and MongoDB.  (To run, you’ll need a local Mongo DB called “todo” with a collection called “tasks”).  It definitely shows the power of both frameworks running together.  In just 75 lines of HTML and 29 lines of JavaScript for the controller, I have a mobile app with full CRUD support.  Hope you find it useful.

NewImageNewImage

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

On-Demand VPN using OpenVPN for iOS

Many large organizations have existing VPNs in place, and the rise in development of enterprise mobile applications often requires that apps running outside the firewall need to “VPN in” before they are allowed to access any corporate resources.

While enabling a VPN is fairly easy on most mobile devices, I’ve found that many IT organizations would like to automate this such that the device automatically connects to the VPN when the Enterprise App or an internal Website is launched. Having gone through this with a couple of customers, I’ve put this post together to highlight how this can be done.

Which VPN types support On Demand for iOS?

iOS 4.2 introduced features designed for the enterprise. These features included several VPN clients (L2TP, PPTP, Cisco IPSEC), many of which can be configured to automatically initiate the connection based upon DNS requests for certain domains.

While this on demand feature has been around for a while, it does have a couple of caveats. Firstly, it’s only available for SSL based VPNs. An SSL-based VPN is a connection that relies on a client/server side certificate for authentication. Having an SSL-based VPN means that the connection can be established without asking the user for credentials (e.g. a password or RSA token). Because an on-demand VPN could be connecting and disconnecting every few minutes, this makes sense as prompting the user could cause a jarring user experience. Secondly, the on demand VPN can only be setup using the iPhone Configuration utility. While you can create a VPN connection on iOS devices (under general/settings), it’s not possible to create an SSL-based VPN or specify any of the on demand domains.

With this in mind, I’ll be showing how to establish an On Demand VPN using OpenVPN and the OpenVPN client for iOS that was released earlier this year.

Server-Side Setup

The first step is of course to setup an OpenVPN server. If you don’t have access to one already, there are plenty of guides to help you set one up. If you don’t have access to a spare machine on the network, you can also use a Linux VM instance hosted on EC2, Azure, or any other hosting provider. This article is a pretty good guide for setting this up on EC2 and the instructions should be able to be tailored to other hosting environments.

Generating Certficates and Keys

Once you have your OpenVPN server running, you’ll need to either import or generate certificates and keys required to establish the connection. If you don’t have access to certificates already, you can find some great documentation here on how to create your own using the EasyRSA project on Github. (Scroll down and look for instructions on using easy-rsa)

These are the certificates you’ll need to generate using EasyRSA:

ca.crt (CA certificate required for both server and client)
dh2048pem (A 2048bit Diffie Hellman key that is required on the server)
server.crt (The server-side certificate)
server.key (The key for the server-side certificate)
client1.crt (The client-side certificate)
client1.key (The key for the client-side certificate)

Configuring OpenVPN 

Place the certificates in a folder called keys (under /etc/openvpn/keys) and modify your /etc/openvpn.conf file to look similar to the following:

tls-server
port 443
proto tcp-server
dev tun
ifconfig 192.168.2.1 192.168.2.2
keepalive 10 120
comp-lzo
persist-key
persist-tun
verb 3
push "ifconfig 192.168.2.2 192.168.2.1"
push "redirect-gateway"
dh keys/dh2048.pem
ca keys/ca.crt
cert keys/server.crt
key keys/server.key

This should be fairly straightforward to understand from the documentation, especially if you’ve used OpenVPN before. As you can see, we are creating a peer to peer connection using two private IP addresses (192.168.2.1 and 192.168.2.2). Don’t worry if these don’t match your internal network on the OpenVPN box – they don’t need to in order to get this up and running.

For the purposes of this article, I have the VPN running on a tcp:443 connect, but feel free to adjust the protocol and port to match your own environment (assuming that you have the necessary ports open on your Firewall).

Once you have the server configured, you can start OpenVPN:

openvpn --config /etc/openvpn/openvpn.conf

Assuming that the server starts OK, you can move to the next step.

Installing and Configuring the Client

The OpenVPN client can be found on the AppStore. At the time of writing it’s version 1.0 build 47, which has a few bugs here and here, but still seems to work well.

After you have this installed, go ahead and install the iPhone Configuration Utility on your Mac. This can be found on the Enterprise iPhone Support page (http://apple.com/support/iphone/enterprise). Don’t worry – although it’s called the iPhone Configuration Utility, this will also work for setting up a VPN on an iPad device also.

After launching the utility, create a new configuration profile. In the general tab, enter the mandatory fields for name and identifier. Then, click on the credentials tab. We need to import the client certificate and key that was generated earlier using EasyRSA.

Unfortunately, the iPhone Configuration Utility (which we’ll call IPCU from now on) doesn’t support importing .CRT and .KEY files directly, so we’ll need to generate a PKCS#12 file for use here. To do this, in the Terminal locate your client certificate and key files, and run the following command:

openssl pkcs12 -export -in client1.crt -inkey client1.key -out client1.p12

The result of this should be a .p12 file, that you can now import into the credentials section of IPCU.

Note:  When you generate the .p12 file, you will be asked for an export password for the file. Enter something, and use the same password in IPCU (there is a field just under the certificate picture). If you don’t enter a password, you will likely get a profile error when you try to deploy this to the device.

With this done, now navigate to the VPN tab and create a new VPN connection. IPCU doesn’t support including an OpenVPN config file, so we’ll have to create the majority of the settings in this tab – this is where things get fun :-)

Give the connection a name, and select “Custom SSL” for the connection type. For the identifier, use the following:

net.openvpn.OpenVPN-Connect.vpnplugin

This is telling the VPN client that a specific bundle ID (the OpenVPN app) should be used for this connection.

Next, in the Server field, enter the DNS name or IP address for your OpenVPN server.

The Custom Data contains keys and strings that replicate what would have normally gone into a config.ovpn file. These are the entries that you will need:

ca – This is a tricky one to get right. We can’t point it to a ca.crt file, because there is no way of bundling a file using the IPCU tool. To overcome this, open the ca.crt file in TextEdit and replace all of the newline/carriage returns with \n. What you should end up with is a single (long) line of text that starts with —–BEGIN CERTIFICATE—– and has several lines delimitered by \n ending with —–END CERTIFICATE—–. Once you have this, paste this entire line into the value for the ca key.

comp-lzo - enter the key, but you don’t have to give it a value.

dev – set this to tun

port – set to 443

proto – set to tcp

(Again if you are using something other than TCP port 443, feel free to change)

remote – set to [your server name] 443

(replace your server name with the DNS name or IP address of your OpenVPN server)

verb – set to 3

Here’s a quick screenshot of my profile:

NewImage

That should wrap up the custom data piece.

Under User Authentication, select Certificate – and then under Credential select the client certificate from the drop down.

Finally, check the “Enable VPN On Demand” box, and in the below table enter the domain names or IP addresses for the hosts that VPN is required for. For this tutorial, I have a single entry for 192.168.2.1 with “Always Establish”.

That’s it!

This configuration should be enough to get VPN On Demand working with OpenVPN on the iOS client. To test, deploy the configuration profile to the device. Assuming that this works, open a browser and browse to 192.168.2.1 – this should invoke the VPN connection and forward the requests to the OpenVPN server. If you have a test page running on the OpenVPN server then this should be displayed in the browser.

If it didn’t work…

There’s a good chance that things won’t work first time, just due the complexity of the setup.  Here are some of the common tips/tricks that I found during the process.

- Firstly, the console window in IPCU will be your best friend. The most common error I saw was related to the CA certificate. If you get these, it likely means that your CA entry in IPCU is wrong. Go back and make sure you’ve correctly replaced the linebreaks with \n’s and retest.

- There are a few “bugettes” in the iOS client. As of build 47 these include:

The tcp-client param is not supported in the iOS client. Use tcp instead.

The client expects ifconfig information to be pushed to it (using the push lines in the server config). It doesn’t seem to be possible to configure ifconfig lines locally.

The “redirect-gateway” seems to be required for the iOS client – whereas Tunnelblick connects without it.

- Workflow. Getting VPN On Demand working right off the bat can be hard, especially if multiple parts of the configuration are wrong. If you are new to OpenVPN, you might want to setup a VPN with a the following configurations (in terms of complexity just to get working):

OpenVPN w/ Secret Key – using Desktop machine (use Tunnelblick for the Mac)
OpenVPN w/ Certificate – using Desktop machine
OpenVPN for iOS w/ Certificate – using the actual OpenVPN for iOS Client (not IPCU)
OpenVPN for iOS w/ Certificate – using IPCU 

- Browser Refresh.  If it looks like everything is working (VPN established, etc.) but you still don’t get your Web page, try refreshing the browser/making a 2nd request.  I’m not sure whether this is something in the config, or a “feature” of the OpenVPN client for iOS – but I’ve found that refreshing often helps brings the page to life after the VPN connection has been established.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

QCamera

Doing mobile development on a Mac? Need to show your mobile device using your USB camera during a presentation?

Here’s a quick utility that I hacked together over the weekend to do just that. Supports mirroring/reversed images (which is why PhotoBooth won’t work for this) and borderless mode to keep it in the foreground over an IDE or presentation. Hope you find it useful!

Available on the App Store Badge US UK 135x40

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Uploading Photos from Mobile Web Applications

Here at Neudesic, we’re fortunate to be involved in many exciting HTML5/Mobile Web applications for different organizations. For many of these projects, one of the common requests, especially for field-facing mobile applications, is the ability to upload a photo from within a web page in a mobile browser.

If you are not familiar with the space, you may think this should be default behaviour, but surprisingly uploading media is one of those areas that is still going through the standardization process. Eric Bidelman has a great overview of the three “rounds” of standardization that have taken place so far as part of the Device API working group.

What can you do today?

While Eric’s article gives a great overview of what’s likely to come, the purpose of this post is to explore what’s possible today, outlining the relative pros and cons of each approach.

Firstly, let’s take a look at what’s supported out of the box:

Android

If you are using Android 3.x+ (i.e. either Android tablets running Honeycomb or later, and Android phones running ICS) – or users are running Chrome or Firefox Mobile for Android, the browser will support an input element that can invoke the camera:

<input type="file" accept="image/*" capture="camera">

Simply add this element to your web page, and together with some server-side processing for the upload, users can upload the image from their device.

Android Image Upload

As Eric mentions in his article, it does look like things are heading towards getUserMedia() instead. Although this new API works with latest versions of the desktop version of Chrome, we haven’t found anything that works on mobile browsers as of yet.

iPhone/iPad

Unfortunately, the input element above does not work on Mobile Safari on iOS5 today – the experience for the user is just a disabled button. This is true for the recently released version of Chrome for iOS also (as it’s just a wrapper over UIWebView).

Things are changing however.  At WWDC this year, Apple publicly announced support for photo and video uploads within Mobile Safari shipping with iOS 6. It’s difficult to say much more about the implementation here (as the developer/beta programs are under NDA), but if you have access to Apple’s developer program, it’s definitely worth checking out.

Apache Cordova (PhoneGap)

If you want to support earlier Android versions, and/or can’t wait for iOS 6, arguably the most popular choice is Apache Cordova (previously known as PhoneGap). Apache Cordova provides a native wrapper around HTML-based content, and supports several platforms today – including iOS and Android. The Cordova API supports media capture, and with a couple of lines of JavaScript, it’s possible to instantiate the camera or invoke the camera rolls within your Mobile Web application.

Camera Roll on iOS

Pros: Works with the most popular versions of mobile browsers, and as of now, Cordova provides a good user experience for the user. The user presses a “add photo” button in the HTML application, and the native wrapper invokes the camera control without the user needing to know whats going on. If using the camera roll, the API also supports the option of uploading multiple photos.

Cons: Using Cordova does however change the deployment model for the application. No longer can you just visit a Web site to use your application – you now need to think about distributing your application – either via the AppStore for public-facing applications or through another channel for enterprise apps.

In addition to the deployment, Cordova also introduces several options that need to be considered for actually transfering the image to the site. The default is to use Base64 encoding, which is good for small images, but we’ve experienced performance problems on large images from 5MP+ cameras. The Cordova API does support a File Transfer API, which works well except it doesn’t yet support authentication, so you’ll need to create an anonymous area to post your photos to. If you do need authentication, you’ll want to send the photo directly after capture, which will likely mean writing a custom Cordova plug in and using NSUrlConnection to send your photo to the server.

Companion Application

An alternative approach to wrapping your HTML content with native code is to ship a “companion application” responsible for uploading the photo.

Both iOS and Android support custom URL schemes, which means that applications can respond to different URL requests from the browser. For example, I can create a native application responsible for taking and uploading pictures, using a custom URL scheme called simonphoto:// which I can then pass various parameters – for example, the ID of a project that I’m uploading photos for. Once the user clicks on the simonphoto:// link within the mobile browser, the application launches and I can take and upload as many photos as I want.

Pros: The biggest draw to this approach is that the HTML application doesn’t need to be wrapped with any native code.

Cons: While I don’t have to wrap my HTML, the user still needs to obtain the companion application, which will likely involve a trip to the AppStore or other link for download. In addition, even when the companion application is downloaded, the user experience isn’t quite as slick as the the PhoneGap approach. For example, in iOS there is no natural way of getting back to the Web app once the native application is ready to hand back control (unless you pass a return or app id in the parameters). Also, there is no way of checking whether the companion application is installed or not from the Web page.

Picup

Picup is an example of a free companion app that works in a similar way as outlined above. It uses the fileupload:// URL scheme to invoke the Picup app, which much be installed.

Picup Application

Pros: As above.

Cons: As above. No version for Android (although I’m sure there are equivalent apps available).

Email

Finally, a very simple approach, but one that I’ve seen a couple of people use is sending the photo via email. Your application has a “mailto” link which includes a subject (maybe the ID corresponding to the application) and body that reads “Please remember to attach your photo”. The user attaches the photo manually and it’s sent to a server-monitored email store for processing.

Pros: Nothing native here, and deployment model stays the same.

Cons: Funky experience for the user. You’ll also need to setup a server side environment to handle the incoming emails, strip the attachments, and correlate with your application.

Summary

A lengthy post, but hopefully it gives you an overview of how to do photo upload from mobile devices today. To summarize:

If you are writing an application that won’t be released for a few months, and will primarily target Android ICS and iOS6, you should be able to use the <input/> element outlined above to invoke the camera and upload a picture. If you do this, make sure you understand the transition to getUserMedia as the specifications mature.

If you are writing an application that needs to target today’s platforms – namely Android 2.x and iOS5, you’ll either need to use Cordova to create a wrapper or a companion application (either hand crafted, or something like Picup). Choosing between Cordova and a companion application is a balance of user experience vs. deployment. A Cordova application will keep the user experience seamless, but you will be responsible for the deployment of the application as a result.

If you don’t want to do any device development, and are just looking to provide a shortcut for users to send photos, you could consider the basic mailto: / email link approach.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Announcing Neudesic Slingshot!

Getting SharePoint working on a mobile device can be hard. The “out of the box” experience, even with SharePoint 2010, is very basic and doesn’t take advantage of the device. Solutions on the AppStore are a step in the right direction, but many don’t do anything over providing the ability to browse a SharePoint site.

At Neudesic, we are hoping to change all this through a project we call Slingshot.

Slingshot is an open source mobile client and library for SharePoint. Built upon the jQuery Mobile and Apache Cordova frameworks, Slingshot makes it ridiculously easy to expose tasks, announcements, documents, and virtually any other object directly from SharePoint to any mobile device.

myWPEdit Image

We demonstrated Slingshot for the first time in public at the SharePointFest in Denver this week, and the response has been tremendous. For those that didn’t make it to the event, I wanted to use this blog post to expand on what the framework can do.

Slingshot is very lightweight, and can be deployed in one of two ways: The code can run on the SharePoint server, and users access it using their mobile browser. Alternatively the same code can run on the mobile device in a native application, with no changes required on the SharePoint server.

Here’s a quick run through of what Slingshot supports today:

SharePoint Lists and Items

Slingshot uses the ODATA support in SharePoint 2010 to expose virtually any list or item to the mobile device. The out of the box demo shows announcements, tasks, and organizational details, and it’s easy to extend to workflows and other lists. Each of these items can be exposed through a form with touch native controls.  For example, task items have a slider control to indicate percentage complete.

Bi-Directional Updates

The sample app also demonstrates bi-directional updating. Update an item from SharePoint UI, and it automatically gets updated on the mobile device. Alternatively, update on the mobile device and the item is automatically updated in SharePoint. This update is seamless, so the user doesn’t have to hit “save” after making the change on the mobile device.

Document Library Support

One of the core scenarios for using Slingshot is to browse document libraries, which Slingshot handles really well. Supported file types (such as PDFs) can also be opened directly from the mobile app.

Integration with Photo Capture

Browsing and opening files from a mobile device is useful, but Slingshot also supports uploading data from the device. The majority of phones now come with a camera. The sample application shows how to take a photo on the device and upload it to a document library or attach it to an item. We find this functionality well suited for field employees who need to interact with workflows that involve taking pictures and uploading them to SharePoint.

Support for Offline Scenarios

Because Slingshot works locally on the device it enables a number of offline scenarios. Currently the application has the ability to work offline, and we are working on synchronization of SharePoint lists and items to the device, which will provide a true offline experience if no connection is available.

Authentication

Authentication works in one of two ways. If you are accessing Slingshot via a mobile browser, the browser will prompt for credentials (the same way as if you’d just navigated to any other SharePoint page). If you are running Slingshot locally on the device, we use a form-based mechanism that can be customized and extended as needed.

Multi Platform Support

Because we’ve developed all of this using jQuery Mobile and Cordova (PhoneGap), it is supported on multiple platforms by default. Both these frameworks support up to six platforms today, including iOS, Android, Windows Phone 7, and Blackberry. We provide default templates for iPhone and Android, and creating new templates for other devices is as simple as creating new CSS files.

Easy to Extend and Update

Apart from the device integration, everything in Slingshot is based on HTML5 and JavaScript. For those coming from a web background, this makes it very simple to extend and update.


Best of all, we’ve licensed Slingshot as an open source framework, under the MIT license. You can get all the bits for free, and we even have other developers that are signing up to contribute.

Ready to see more? If you didn’t have an opportunity to stop by the booth at SharePointFest in Denver, check out the repo on GitHub – or drop me a line using the contact form if you’d like more information. Neudesic is actively extending this framework for many other scenarios and customers, and we’d be happy to help you extend this for your own needs also.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

An Objective View of MEAPs

I recently had the opportunity to put together some research for a customer who has been interested in the MEAP (Mobile Enterprise Application Platform) space. My premise is that the market has become flooded with MEAPs (Mobile Enterprise Application Platforms, as coined by Gartner), yet most of them are fundamentally taking organizations and developers down the wrong path when it comes to developing mobile applications. The problem is that MEAPs demo really well in front of the CIO… “Wow! You just hit F5, and your application is compiled and deployed to iOS, Android, Blackberry devices… Where do I sign?” – yet the reality is very different. Namely:

Language Abstraction – Many MEAPs have their own language that claim to be similar to Java or a flavor of JavaScript. Even if it is the same language, there is always something new to learn. Also, developers tend to shy away from learning any language that’s vendor specific (APEX on Force.com anyone? ;–)

Language Limitations – When you create a language that abstracts other languages you always end up serving only the lowest common denominator. Often there are ways of coding styles and nuances supported in the native language that the MEAP won’t expose because it’s not on other platforms.

Platform Limitations – Time has shown that platform abstraction doesn’t work (do a search on Wikipedia for cross platform RAD tools if you don’t believe me). Also, platforms change quickly. What happens if/when the next version of iOS is released? You have to wait for your MEAP vendor to catchup before you can use any of the features.

UI Limitations – Following on from the previous point, many of the controls that MEAPs offer also follow the lowest common denominator rule. For example, Cocoa Touch has a neat feature called a “Half Page Curl Transition”. If you abstract your UI to a MEAP vendor, how is this supported on other platforms? Either a) it’s not (so by default you can’t use it on iOS), b) you can only use it on iOS (which breaks the promise of a MEAP) or c) it’s implemented as a hack job on all platforms.

Tooling – MEAP tooling is often Web based, or bundled as an Eclipse add-on – but in both cases it often doesn’t fit in with the other tools that developers use today (e.g. ALM, refactoring, unit testing, etc.). Also, many of the MEAP vendors seem to be aiming their toolsets towards business analysts. When are we going to let this one go? Business analysts have an important role to play in teams, but they shouldn’t be developing UI, and they shouldn’t be writing code.

Debugging – Let’s say you create your application with a MEAP, and then it crashes 1 time in every 10 (i.e. one of those really nasty bugs to find). What are you going to do? a) Reach out to Apple? I suspect they won’t help you. b) Search the web for other people with the same issue? Could be difficult to find. c) Pay the MEAP vendor even more money to investigate your issue? Ah, that’s the one…

Data Abstraction – Many MEAPs offer connectors to databases, XML files, SAP, etc. Not only are these costly, but many are just pass-through connectors, so as a developer you don’t get any control over the connection. Want to implement synchronization? Want to change the formatting or query for better optimization? Probably not going to be possible.

Difficult to Extend – Many MEAPs don’t extend very easily. Found a new JavaScript library that you want to use in your application? How about a native control that you’d like to display? Could be tough. Some MEAPs do offer bridging to native code – but in which case, why not just write the whole thing in native code to start with?

Vendor Lock In – The sum of all the above leads to quite the definition of vendor lock in. Chances are by the time you deploy your first application you’ll be signed up with an expensive support and service agreement, with your developers working on code in a language that they’ll never be able to re-use, on a platform that won’t go anywhere.

I’ve extended this into a presentation that you can find below – which cover the above points in more detail, plus outline some general alternative approaches to creating applications without the dependency on a MEAP framework.

Based on other people’s experience with MEAPs, am I missing anything?

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Tips, Tricks, and Recommendations for HTML5/Mobile Web Development

Over the past few months I’ve been fortunate to have worked with several customers creating Mobile Web applications for different devices. These have included an iPad based Mobile Web app for a healthcare provider, a cross-platform Mobile Web app for a commercial real estate broker, and an Android tablet solution to allow scientists to research experiment details from the comfort of their lab.

From these projects, I’ve come up with a list of tips, tricks, and recommendations that I wanted to share if you are looking to develop your own Mobile Web applications. Hope you find them useful…

Understand the differences between Mobile Web and hybrid applications

It’s important to make an early decision on whether your application is going to be pure Mobile Web (the user accesses it through the browser on the device) or hybrid (the user launches an application with an embedded control to display web based content). The decision to use the mobile browser or to have a dedicated hybrid application will likely be determined by the functionality the application requires. For example, obtaining the GPS location from the device can be performed perfectly well inside the browser, but accessing the camera from a Web page needs a hybrid application to provide the functionality.

In my experience there are three common features that drive developers towards a hybrid application: 1. Access to the camera. 2. Access to local contacts on the device. 3. Deployment to the AppStore/Marketplace. The first two are to overcome limitations of what can and can’t be accessed through the mobile browser (and is something that Mozilla is trying to tackle through WebAPI). The latter one is probably the most important to understand however – as while a hybrid solution will enable the application to be published to the app stores, extreme care needs to be taken to ensure that the application will not be rejected. This is most common with applications destined for Apple’s AppStore (if Apple view your application as a single container for web content with no apparent native functionality, they will more than likely reject it).

If you do take the hybrid approach, you really have two options to build the application – you can either set out and build a native application, embed a WebView control and then hook different events to create your own bridge between the two. This can be very useful if you only have a small piece of Web functionality that you need to embed in your application. Alternatively, you can consider using a framework such as PhoneGap (now known as Apache Cordova). Using Cordova is not without it’s challenges (for example, with cross domain scripting and client side certificate authentication), but it can definitely give you a head start especially if the majority of your application is going to be based on mobile web content.

Setup a robust development and testing environment

Setting up a robust development environment might be viewed as obvious for most of us, but tools for developing Mobile Web applications are still relatively immature, so it’s an important area to get right before you start your first app. In the most basic setup, you are going to need three things to be successful:

The first is a great IDE for HTML development. You’ve probably got your favorite already, but a strong IDE with as much JavaScript code completion support as possible will be your friend. Personally, I switch between TextMate, Visual Studio 2010, and WebStorm depending on which platform I’m working with. It’s also interested to see where Adobe are headed with their toolset.

Secondly, you are going to need a browser capable of inspecting the DOM and doing JavaScript debugging. Personally, I use Safari for doing this, but Chrome and/or IE9 will equally provide you the tools that you need. The important thing here is not so much the choice of the browser, but the understanding of how to breakpoint JavaScript code and inspect elements both on and off the page.

Finally, you’ll need some kind of device, or device emulator. Switching the user agent on a desktop browser will only get you so far, and eventually you are going to need to test on something representative of the device that the user will be using. If you are developing an application that will be primarily used on iOS devices, I would certainly recommend a Mac (as the iOS simulator is very robust). If a Mac doesn’t float your boat as your development machine however you could consider a hosted solution such as MacinCloud or simply do all your debugging using an iPod touch. There are a few PC based utilities that claim to emulate mobile safari/iOS, but I’ve had a poor experience with all of them.

For Android, I tend to avoid the emulator whenever possible (it’s a resource hog) and instead have a selection of devices that I can use for debugging on the fly. I’ve found that the key for Android testing is to have a selection of devices with preferably different resolutions and running different versions of the OS (e.g. a separate device running 2.1, 2.2, 2.3, and 4.0 should cover most of the current market, unless you have a need to go back to 1.6 for some reason). If you don’t have access to physical handsets, you may want to consider one of the testing providers such as Perfecto Mobile. They have a variety of devices that you can rent, covering many different platforms.

Use client side JavaScript instead of server side scripting

If you’ve been developing Web applications for some time, especially enterprise facing applications, you’ll be used to having a lot of the presentation and application logic tied up in server side scripts, maybe running server-side ASP, ASP.NET, JSP, PHP, etc. When developing Mobile Web applications however, things need to change. While server-side scripting will of course still work for a mobile application (and might be very tempting as you start to write your first application), it quickly creates a tight coupling between your device and the server. In the old days where you were accessing the server from a desktop browser on the same network, this wasn’t a problem – but once you move the experience to a mobile device with a potentially patchy network connection, the last thing you want to be doing is relying on the server side for generation of pages and views. If your mobile web application needs to do a roundtrip to the server when you hit the “Next Page” button, you’re going to be heading for a world of hurt.

The answer is to move as much (if not all) of the application logic to client-side JavaScript. This might be a painful exercise as you translate the move from an MVC server side framework to handcrafting page navigation using client side JavaScript, but the pay off will be worth it. If you have all of the application logic locally, together with pre-fetching as many of the pages into the DOM when your application first loads, you effectively disconnect yourself from the server side which makes performance much better and also moving to offline much easier. Of course, you still want to communicate with the server side – who doesn’t? – but this should be done via a set of asynchronous REST/JSON calls to bring data into the application rather than relying on the server to generate HTML for your application.

Design for running offline

Related to the previous point, you should also start thinking about how your application could run offline, even if you have no plans to do so. This will put you on a good architectural path, and will also mean that your application will work if and when network connectivity is lost. There are plenty of articles explaining how to enable offline access in HTML5 applications, so I won’t plan to cover here – other than to say you’ll be creating a cache manifest for your application, specifying the files to go into your cache, enabling the scripts for checking the cache when your application starts, and handling control logic accordingly (e.g. when you hit that submit button, you’ll want to know whether there is network connectivity before making the call to the server!).

If there’s one piece of advice that I can offer here however (and we learned this the hard way) it is to design for offline first, but implement last. Do all of the right things to support offline in your application, but don’t enable it until you are close to the end of your development cycle. If you enable it too early, it can cause mayhem with the development team – as your developers could end up debugging against a version of the application that could be slightly older – or the cache doesn’t get refreshed in the way it should. This doesn’t application to local storage – this is fine to access during development – I would just recommend not enabling the cache manifest until you go into UAT.

Select the right UI framework for your needs

Almost every other day there seems to be a new HTML UI framework released, and mobile frameworks are no exception. At Neudesic we’ve had most experience and success using jQuery Mobile, but have equally done work using Sencha, Dojo and others. As all the frameworks offer slightly different combinations of controls, I’ve found one of the tricks for selecting a suitable framework is to first build out a list of the controls that you are likely to need. For example, in one project we developed a set of paper prototypes (side note – I really dig UI Stencils for this) and realized that we would be creating a multi-tabbed application, with many lists on each page. Knowing what controls we were likely to use ahead of time made selecting the framework easier, and also put into perspective what controls we would have to build from scratch.

The good news is that most of the frameworks have demo pages/sites available, so that you can check them out beforehand without having to download anything. This can be a great way of testing the controls across a different number of devices, as well as getting a feel for the performance. My rough order of magnitude is that HTML based mobile UI will feel around 85% of a native control – it will look similar, react similar, but you just know that there’s this 10 – 15% gap that doesn’t quite feel native.

Understand the caveats with implementing maps in Mobile Web applications

Related to the last point, many applications have a need to display maps and pinpoints, and this will likely remain true for many mobile web applications that you might be creating. Based on experience, there are a couple of caveats that need to be understood before you head down this path.

Firstly, performance on Mobile Web map controls is not to par with native controls. Using Google Maps in Safari on iOS seems sluggish when comparing it to using MapKit in a native iOS application. I’m not sure what optimizations have been done in MapKit to give it the performance it has, but the difference is quite noticeable. As a result, if your application has a fundamental need to do a lot of mapping (i.e. if this is it’s primary function) you may want to consider a hybrid approach where you navigate to native pages for the mapping as part of your application.

Secondly, the web control for Google Maps (and this probably applies to other mapping controls) likes to “own” the page – which can put it into conflict with UI frameworks such as jQuery Mobile. For example, when you change pages in jQuery Mobile, the DIV element of your current page is set to hidden, and the DIV element of the new page to block. If your map control is embedded on a page that gets set to hidden this can cause Google maps to have a hard time. We’ve experienced random behavior such as the map control not updating or repainting correctly when it is brought back into focus. This can be overcome by an event on the page load to refresh the map canvas (example below), but it’s one of those bugs that takes a lot longer to find than it does to fix.

$(‘#mappage’).live(‘pageshow’, function() { google.maps.event.trigger(map, ‘resize’); });

Think ahead for non-standard UI elements you are likely to need

While frameworks such as jQuery Mobile will provide standard controls such as buttons, lists, labels, and radio boxes, your application will likely have a need for elements and controls that are non-standard. These can include tables, grids, and image carousels to name a few. Many of these can be created using custom controls, but before going down that path, I always try and ask myself two questions:

Firstly, if the control does not exist, does that mean a better UI nuance is available for the device? For example, there are few mobile web controls for displaying datagrids on mobile devices. Rather than force-fitting a solution that might not work well on a 3.2″ screen, think about what alternative solutions could be used instead. For example, maybe a series of cascading list controls would actually provide for a better user experience over some custom hacked-together table control. When in doubt, try to look at how other mobile applications have used controls to represent a similar data set.

Secondly, if the control does seem to fit, but it’s just not included in the standard UI framework that you’ve chosen, think about searching for a third party solution before re-creating something new. This can apply to image carousels (PhotoSwipe is one of my favorite controls for doing this) as well as charting (there are several really good JS based charting controls out there).

Make your mobile web app look and feel like it belongs with native applications.

Why not go that extra step and have your mobile application look like it belongs with other native applications on the device? A couple of small recommendations for this one:

Firstly, never show the address bar in your mobile application. Simply use a <viewport…/> tag to have your application run in full screen mode. The user will still be able to get to the address bar, but it will be hidden from view by default. (side note – jQuery Mobile now performs this automatically without the need to do “scroll to” events in JavaScript).

Secondly, if you are targeting iOS devices, consider using Cubiq’s AddToHome JS library. This is an excellent add on that will display instructions for the user to add the application to the iOS home screen, enabling the application to have it’s own icon and run completely full screen when launched.

Don’t go creating your own username and password database

Have users sign on to your application can be very useful for security of the application and for storing preferences and other settings. Unless you have a very strong reason however, I recommend that you avoid creating your own username and password database for your application. Doing so can seem really easy at first, but as your application gets more popular you’ll be left with a nightmare situation of having to deal with registration issues, password resets, and all of the other administration that comes with owning your own identity provider.

If you are building a mobile web application for the enterprise, I suspect you’ll already be thinking about this – either hooking in to an existing Active Directory instance or other identity provider (although you’ll likely need to consider how this will work outside the firewall when your mobile users are accessing your application via a public connection).

If you are building a public-facing application however, an efficient solution can be to federate with an existing identity provider. Chances are your users already have a Google, Yahoo, or Facebook account. Why not take advantage of this and use this sign-in information to authenticate the user for your application? This can be done in a couple of different ways – either with a native SDK from one of the providers – or using a federated service such as Microsoft Azure’s Access Control Service. This is a simple service to setup, which will enable you to configure a list of providers and returns a bag of claims to your application which you can use to match up with a list of settings, preferences, etc. There are a few caveats with this approach, especially as some of the providers return the information via a post back (which can really upset your mobile application if you’ve pre-fetched all of the pages in to the DOM beforehand). This is something that I’ve written previously about in this post.

Make your Mobile Web application perform well

It might sound obvious, but if you want your Mobile Web application to come anywhere near to the performance of a native application, you’ll want to keep a keen eye on performance. Generally, I’ve found there are three main causes of bad performance in Mobile Web applications:

First is server-side generation of the UI and round tripping (as discussed in the point on client-side JavaScript earlier). If you are generating any of the UI on the server-side or making any synchronous server-side calls, you are more than likely to run in to trouble.

Second is too many CSS effects/transitions. Many of the UI frameworks, including jQuery Mobile, include several page transitions for when the user navigates between different pages. Unless you are exclusively targeting iOS devices, I would recommend turning all of these off. Many of the older Android devices don’t implement a version of Webkit that supports hardware acceleration – plus they are running on less capable hardware – so to avoid creating an application that stutters on Android devices, it’s best to disable any transitions and effects.

Finally, watch out for too many registered JavaScript events (especially on the class level). The JavaScript performance on mobile browsers can be much lower than desktop equivalents, and if you are not careful you can end up where the performance of the browser is being compromised by too many registered events. Often this will only add 100ms to various events, but combine this with specific events (such as a button tap) that must immediately navigate to another page, any delay over 100ms might be enough that your user thinks that the button wasn’t pressed correctly. They’ll press it again, and before you know it you have two JavaScript navigation events that you’ll need to handle.

Wrapping up

A bit of a lengthy post, but I hope that this is useful if you are heading down the path of developing Mobile Web applications. If you’d like more information on this, or maybe to share with colleagues, I’ve uploaded this presentation to SlideShare that goes through the above list in some detail.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Extracting and Using Facebook OAuth Token from ACS

A couple of my previous blog posts have shown how AppFabric ACS (Access Control Service) can be used as part of the Windows Azure Toolkit for iOS to enable federated authentication with Facebook, Google, Yahoo, and other providers.

I was recently asked whether it’s possible to extract an OAuth token as part of the ACS sign in process that can then be presented to Facebook’s Graph API in order to access details such as friends lists, photos, etc. In this post, I’ll cover how this can be done.

The first step is of course to display the authentication page. As you’ve seen in previous posts, this can be achieved using the following:

WACloudAccessControlClient *acsClient = [WACloudAccessControlClient accessControlClientForNamespace:@“iostest-walkthrough” realm:@“uri:wazmobiletoolkit”];

[acsClient showInViewController:self allowsClose:NO withCompletionHandler:^(BOOL authenticated) { if (!authenticated) { NSLog(@"Error authenticating"); } else { WACloudAccessToken *token = [WACloudAccessControlClient sharedToken]; NSString *securityToken = [token securityToken]; ... }
}];

In the application, this will display the federated login dialog, and prompt the user to enter their Facebook credentials.

myWPEdit Image

You’ll notice that the ACS client returns a cloud access token, of which a security token can be extracted. This security token is a set of claims returned from ACS. Here’s an example:

http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration=2011-11-11T22:00:00.3593475Z&http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress=me%40simonguest.com&http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name=Simon+Guest&http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier=677830765&http://www.facebook.com/claims/AccessToken=AAADWLwgHWSUBABBXdxbhJB0ZBtA3VOfPSsqzKKwObAtW2rb8EGGTQ8EvnvAdNOcZAGpKfV2gSGbNg7f0gxk4BhI1rhzKEn17VLw343gZDZD&http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider=Facebook-235497486506277&Audience=uri:wazmobiletoolkit&ExpiresOn=1321044986&Issuer=https://iostest-walkthrough.accesscontrol.windows.net/&HMACSHA256=bnvyPmX4/PcWhiImgVVIvSqwHpc4cfi0vI6%2b/BSDK0Q%3d

If we want to make follow on calls to Facebook’s Graph API, we are going to need to present the Facebook User ID and an OAuth Token. Fortunately both of these can be extracted from the token.

To extract this, we first HTTP encode the token:

NSMutableArray *httpEncoding = [NSMutableArray arrayWithObjects:[NSArray arrayWithObjects:@"%3a",@":",nil], [NSArray arrayWithObjects:@"%2f",@"/",nil], nil]; 

while ([httpEncoding count] >= 1) { securityToken = [securityToken stringByReplacingOccurrencesOfString:[[httpEncoding objectAtIndex:0] objectAtIndex:0] withString:[[httpEncoding objectAtIndex:0] objectAtIndex:1]]; [httpEncoding removeObjectAtIndex:0]; }

NSError *error = NULL;

Using a simple RegEx search we can extract the Facebook User ID:

NSRegularExpression regex = [NSRegularExpression regularExpressionWithPattern:@“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier=([0-9])” options:0 error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:securityToken options:0 range:NSMakeRange(0, [securityToken length])]; firstRange = [match rangeAtIndex:1]; fbuserId = [securityToken substringWithRange:firstRange];

And the required OAuthToken:

regex = [NSRegularExpression regularExpressionWithPattern:@“http://www.facebook.com/claims/AccessToken=([A-Za-z0-9]*)” options:0 error:&error];

match = [regex firstMatchInString:securityToken options:0 range:NSMakeRange(0, [securityToken length])]; 
NSRange firstRange = [match rangeAtIndex:1]; 
oauthToken = [securityToken substringWithRange:firstRange];

Now it’s just a case of calling the Graph API using these credentials:

NSString *graphURL = [NSString stringWithFormat:@“https://graph.facebook.com/%@/friends?access_token=%@”,fbuserId,oauthToken];

For the purposes of this post, let’s take a quick look at my list of friends.

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:graphURL]];
NSURLResponse *response = NULL;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *friendsList = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
regex = [NSRegularExpression regularExpressionWithPattern:@“id” options:0 error:&error];
NSUInteger friendCount = [regex numberOfMatchesInString:friendsList options:0 range:NSMakeRange(0, [friendsList length])];

Displaying the friend count in a UIAlertView on the screen shows how popular (or not!) I am:

myWPEdit Image

A simple example, but hopefully this shows not only that you can authenticate against Facebook using AppFabric ACS, but also how the returned Facebook User ID and OAuth Token can be used to make further calls to Facebook using the user’s credentials.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Working with the Windows Azure Toolkit for Android

At the end of August, Microsoft published the Windows Azure Toolkit for Android. At Neudesic, the partner behind developing the both toolkits for iOS and Android, we’ve been working with customers that use the toolkit to connect mobile applications to the cloud. One of the recent requests however has been to provide a walkthrough of getting started with the toolkit. The current build on GitHub was released for a specific version of Eclipse and the Android tools, and as a result, can be a little challenging getting the library and sample code up and running.

In this post, I’ll explain what it takes to download the toolkit, create a brand new environment in Eclipse, and get started quickly with the toolkit.

Getting Started – What You’ll Need

Firstly, there is a list of tools that you’ll need to download.

1. Eclipse. Download from http://eclipse.org – we’ll be using Helios in this tutorial.

2. JDK. We’ll be using the default that ships with Mac OSX, but if you are on a PC, you’ll need JDK 1.6 or higher.

3. Android SDK and Eclipse Tooling. Download the Android SDK from http://developer.android.com (we are using r14 for this walkthrough). Also follow the instructions for configuring the Android tooling within Eclipse. After you have installed everything, use the AVD manager to setup a new AVD for an Android 2.3.3 device.

Setting Up the Library in Eclipse

To import and build the library in Eclipse, perform the following steps.

1. Download the Windows Azure Toolkit for Android from GitHub. If you have the Git client installed, you can use this command:

git clone https://github.com/microsoft-dpe/wa-toolkit-android

Otherwise, go to the site and pull down the zip file of the repo.

2. Create a new directory for your Eclipse workspace:

mkdir wa-toolkit-android-workspace

3. Launch Eclipse, and point the default workspace to this newly created directory:

myWPEdit Image

  1. Create a new Android project called AzureLibrary, set the target to Android 2.3.3, use com.microsoft.cloud.android as the package name, but do not create an activity or test project.

myWPEdit Image

  1. Right click on the AzureLibrary project and select Import. Choose General / File System as the import source, and click on Next.
  2. Browse to the /library/src/com folder in the toolkit folder that you downloaded from GitHub.
  3. Click on the Browse (into folder) button and select the src folder under your project. Expand the src folder, and check the com folder as shown in this screenshot:

myWPEdit Image

  1. Click on the Finish button. The import will complete.

myWPEdit Image

  1. Right click on the project, select properties, and change the Java compiler version from 1.5 to 1.6. (The default is 1.5, yet the toolkit uses many constructs only supported in 1.6)

myWPEdit Image

  1. Click OK, and say yes to rebuilding the project. The project should now build with no errors.
  2. Assuming everything builds correctly, right click on the project, and select Properties again. Go to the Android setting, and click on the Is Library check box.

myWPEdit Image

Setting Up the Sample Application in Eclipse

To import and build the sample application in Eclipse, perform the following steps:

  1. Create a new Android project called AzureSample. Select Android 2.3.3, set the namespace to com.windowsazure.samples.sample, and choose not to create an activity.

myWPEdit Image

  1. As you did with the library, right click on the project, and select Import. Select the /samples/simple/src as the source and import into the AzureSample/src folder.

myWPEdit Image

  1. Right click on the project, select Properties, select Android and add a reference to the AzureLibrary project:

myWPEdit Image

  1. Right click on the project, select Import. Import from the /samples/simple/res folder into the AzureSample/res folder. This will import the resources required for the sample application.

myWPEdit Image

Answer yes when prompted to overwrite the main.xml file.

  1. Right click on project, select Import and select the file system again. Select the AndroidManifest.xml from the root of the source directory and import into the root of the destination project.

myWPEdit Image

The Sample project should now build with no errors.



Configuring your Windows Azure Account Name and Key

In order to setup the sample project, you need to supply your account name and key, as provided by Windows Azure. You can obtain this by logging into the Windows Azure Portal (http://windows.azure.com) and navigating to Storage Accounts to obtain the details.

When you have the name and key, perform the following:

  1. In the sample project, open ProxySelector.java from the src/com.windowsazure.samples.sample package.
  2. At the top of the file replace the ACCOUNT and ACCESS_KEY values with the account name and access key for your Azure storage account.

 

Running the Sample

1. To run the sample, right click on the sample project, select Run As / Android Application.

  1. Once the emulator is up and running, unlock the device.
  2. Refer to the LogCat/Console window in Eclipse if there are any errors.
  3. Click on the Start button in the sample application.
  4. Select either table, blob, or queue storage and browse the storage associated with your Windows Azure account.

myWPEdit Image

That’s it! Your sample application is now up and running, and you are able to browse Windows Azure storage!

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Upgrading your Windows Phone 7 to Mango RC

In late July, Microsoft announced availability of a new build of Mango, build 7712 – also commonly known as the RC Build.  Given that we are close to RTM, yet it may still take carriers some time before deploying Mango to your device, you might be itching to try out the new bits.  If you are, but don’t know where to start, I’ve put together this quick guide based on my own experience of updating my phone, an AT&T Samsung Focus.  Note: As you would expect, if you do decide to upgrade your phone, this is entirely at your own risk.

Before you begin, you’ll need a few things:

1.  A Windows Phone 7 device with all of the current updates (a.k.a. NoDo) installed.  Double check the updates in the Zune application to make sure everything is up to date.  You should see that your WP7 build number is 7390.

2.  Zune Software 4.7.1404.  Although 4.8 was released yesterday, you won’t be able to do the update with this version (yet).  Download 4.7.1404 from here if needed.

3.  Windows Phone 7 Support Tools.  You can download this from here (32bit, 64bit).  Run the installer, but you don’t need to run the application.

4.  Enough battery power to get you through several updates (when the phone is updating, your device isn’t being charged).  I would avoid trying this with anything less than 50% charge.

5.  The mango update tools.  If you are a registered Windows Phone 7 developer, you can supposedly download these from the Microsoft Connect site.  If you are not (or like me you are, but couldn’t find the tools on Connect), you can find a version of the tools on this site.  (Note:  Follow Step 1, and yes, you have to wait for 45 seconds for the download link to work).

With all of the above in place, run the Update.bat from the Mango update tool download.  Assuming there are no errors, you should see something similar to the following.

image

Firstly, the tool will make a backup of your device to the c:\PreMangoState2 directory, and install the updates necessary for your device to receive the pre-release Mango bits.  The time this will take may vary, but on my machine it took 112 seconds to backup, and 70 seconds to update the device.

Once the batch file completes, and the device reboots, the Zune software should automatically launch.  You’ll be shown that an update is available (likely build 7403).

image

Choose to install this, which will then download the Zune 4.8 software.  After the Zune software has been updated, the phone will be updated to 7403, which should be a fairly quick update.

As the phone reboots once more, the Zune software will do another check – and this time will pick up the 7712 build, which is Mango RC.  Choose to download and install this one.  This is where the battery power is important, as this install can take quite a bit of time to complete (let’s just say that I’ve been able to pen this blog post, and it’s still not 75% of the way there!).

Be patient though – one final reboot, and you’ll be running the latest Mango RC (Build 7712) bits!  Enjoy!

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS