Sunday, November 18, 2012

Hours' worth of hidden gotchas and forgotten details

My previous posts about making mobile apps with Phonegap/Cordova, ended with launching the simulators and running the sample app. Today's project was to get a have the page load to a simple Leaflet map centered on my location. This is about the simplest non-trivial app possible, but it took me about 4 hours because of the hidden gotchas.

So, here are a few of the snags I hit upon. If even one of them saves you even a half-hour of puzzling, you're welcome. :)


After my first draft, I threw out my project folder and used ./create to make a new one as before.
 This new one lacked the assets/www folder and its behavior was "Hello World, YourAppNameHere!" Creating a new www folder, and copying the content of the demo app out of Phonegap's folder, didn't change anything. I even went as far as destroying the project folder, using ./create again, and getting the same result: no www, and creating one doesn't help.

The solution was to move Phonegap out of C:\Program Files where I had it. It is now C:\Users\Gregor\phonegap-2.2.0 and it creates new projects perfectly, even with their www content.

I don't know what was going wrong, as I'm an admin account, and copying files out of C:\Program Files shouldn't have been an issue.. But short version: My previous advice about using C:\Program Files may not work as well as I had thought, after a few more creations.


To deploy an app onto your phone, you will need the Google USB Driver. This allows communication between the Android SDK and the phone's innards. This is not the same as using your phone as a Disk Drive or USB Storage device.
  • Go into the Start menu, type "android" You should see android.bat as an option. Click it.
  • This opens the Android SDK Manager. Scroll down to Extras and make sure that Google USB Driver is listed as Installed. If it is not, check it, click Install 1 Package, and then close the SDK Manager.
The SDK Manager doesn't install the driver at all, but merely downloads the driver INF files. You still need to install them, and that process varies by your operating system. Fortunately there is a decent writeup about this already:

On my device (an HTC Incredible, which was hot stuff in 2010) the Google and OEM drivers do not work. For the HTC Incredible, I used HTC Sync from HTC's website. Despite its name, it also involves that special USB driver.

Once these two surprises were taken care of, I can now deploy my Leaflet app to my old phone, and it works A-OK.


When I tried to run my app on the borrowed iPad, it wouldn't build: The profile doesn't have a valid key for signing the app. Evidently deploying your own app onto your own iPad, you still need Apple's permission. And getting it was a half hour of looking up documentation about "provisioning profiles" so I could get permission to develop on my own iPad.

* Connect your iPad to your Mac. In XCode, look in the upper-right to find the Organizer, and look in the Devices section. You should see your iPad listed, including an Identifier, a Provisioning section, and a list of Applications which you have installed onto it.
* Do a Google search for "ios provisioning portal" and follow the link, logging in to the iOS Dev Center. Presumably you already have an account here if you signed up for a developer license.
* After you log in, follow the link for iOS Provisioning Portal, then use the Development Provisioning Assistant. This is a somewhat lengthy wizard, which will walk you through several steps.

Eventually, you will have imported your new identity into XCode and will have tagged your iPad with an identity as well, and Apple and XCode will allow you the privilege of installing programs onto your own hardware. (and folks gripe that Microsoft is invasive and controlling?)


This one caught me by surprise: I got my app loaded onto my iPad, but it wouldn't run. If I put alert() statements into index.js they would execute, but the deviceready event would never happen.

Turns out, cordova-2.2.0.js is not the same between platforms. The first 100 lines or so are the same (which is what threw me) but it's definitely the case that they are different later on.

In my case, I have the one codebase stored on a network drive, and I don't want to copy each file over before each editing session. My solution is as follows:
  • I copied in both versions of the cordova.js, naming them IOS-cordova-2.2.0.js and ANDROID-cordova-2.2.0.js
  • In index.html I have <script> tags for both versions, and one is commented out.
  • When I want to compile or test on a platform, I comment and uncomment the appropriate <script> tag.


The app was now almost running: it starts, and up comes Leaflet, but no tiles! Fortunately, XCode finally came through and gave me something to go on: "whitelist failed for"

A straightforward problem: iOS requires a whitelist if they're to make network access (Android does not). This is in the project's Cordova.plist file. Look for the ExternalHosts setting, and simple add an entry for * (yes, a single asterisk as a host name)

This will enable all hosts, and now my Leaflet app works.

It's up to you if you would rather list individual hosts. Personally I find that an unnecessary nuisance, since I'm the author of the app and I doubt that it could be tricked or hijacked to access other sites.


After learning and solving these hurdles (getting Apple's permission, finding HTC's special USB drivers, reinstalling Phonegap, and more) everything is working: One tap and I have a Leaflet map centered on my location.

Next steps: make this app something worthwhile...

No comments:

Post a Comment