Wednesday, July 30, 2014

Mobile Development with Cordova (Phonegap): Chapter 9

Chapter 9: Debugging with weinre


Smartphones and iPads do not have Firebug, F12 Tools, etc. but there is a tool called weinre which can fill the same role. weinre is Web Inspector REmote. The author says it can be pronounced like "winery" or like "wiener" which I consider a great show of sportsmanship and humor on his part. :-)

A basic overview:
  • weinre runs as a server listening on a socket
  • it's written in Node, so will run on OSX, Windows, and Linux
  • your index.html embeds a <script> tag which loads weinre into the running mobile application
  • you point your PC's browser at weinre's console page, and get a virtual console much like Chrome's F12 tools, with the other end connected to the mobile app
So, steps:

Install NodeJS and weinre
These are well documented on their respective websites, and I don't need to repeat it.

Start up weinre and note the port number
Again, this is documented as part of weinre's own process. The important part is to take note of the TCP port number, then to verify that this port is allowed into your PCs firewall. Linux and OS X, you would adjust your firewall settings to specifically allow this port number. On Windows, you would enable that port specifically for the application node.exe

In our case, we set up weinre on our web server instead of on a local PC, so that we could use it on our various projects without dealing with the variations in our PCs' individual firewalls. This also allows us interesting opportunities, such as having me check out the console while the app runs on someone else's phone -- something you can't do if your weinre is running on localhost on your LAN.

Add the <script> tag
Insert this code into index.html:
<script src="http://192.168.100.1:8080/target/target-script-min.js#YOURAPPNAME"></script>


Replace YOURAPPNAME with some meaningful name for you app or session. It could be your app's name, your own name, anything that would keep two people from becoming confused if they were using weinre at the same time.

Of course, replace 192.168.100.1 with the hostname of your own weinre server, be that your own PC or the one you run on your website.

Open your browser
Then visit the corresponding URL where YOURAPPNAME matches whatever you used in the app:
http://192.168.100.1:8080/client/#YOURAPPNAME



This opens up the virtual console, where you can begin inspecting the HTML, inserting JavaScript via the console, and so on.




Actually having the F12 developer tools available, is a huge step forward in being able to debug the app once it's on your phone. If you go with the web server setup like we did, you can even have one of your beta testers run the app as you load the console. This is invaluable when debugging issues that only happen on their hardware and not yours.


Saturday, July 26, 2014

Mobile Development with Cordova (Phonegap): Chapter 8

Chapter 8: Tips on Writing Your App

Now that you can compile and distribute your apps, the hard part is past... and now comes the lengthy part, actually writing out your application, then revising it repeatedly as specs change and budgets dwindle. That's all on you: if you're using this tutorial then you should know enough about web development to do that on your own.

But, here are a few pointers and pitfalls that may help you out.

MobileMapStarter

First, I'll get the self-promotion out of the way. I have written up a starter app, which includes jQuery mobile, leaflet for doing maps, a good starting place for a welcome page, a settings panel, and so on. You may want to check it out.

https://github.com/gregallensworth/MobileMapStarter

Choosing a HTML/CSS framework

jQuery Mobile is quite popular, and we use it quite a lot here at GreenInfo Network. The big bonus is that it is jQuery and therefore ubiquitous, with a very large community and a startling number of plug-ins, hacks, and known workarounds. It is also very much based on HTML, and therefore as the lowest barrier to entry of most mobile frameworks, by virtue of letting you use HTML, CSS, and JavaScript much as you normally would.

It is not a panacea, however. The applications tend to look very "canned" and not entirely native as much as mobile-friendly websites (which is the point). The responsiveness isn't always great either; it definitely feels slightly more lagging then a truly native app.

You can ask Google for a plethora of other frameworks and opinions. Lately, we have become interested in Ionic which is based on AngularJS. This technique involves a more programming than HTML, and requires more structure instead of chaos, but in return, the apps tend to load up very quickly and to feel very fluid and responsive during use.

Fastclick

Most HTML mobile frameworks, and a time delay on processing your taps. This is meant to detect a double-tap, but in reality it just makes your app seem lag. He as it ignores you for quarter of a second.

Check out the Fastclick library. This JavaScript file and one command, removes this time delay to make your apps seem more responsive. If you use this with jQuery Mobile, you'll probably want to use the .click() event instead of the .tap() event.

Local CSS & JS

You should really include all of your JavaScript and CSS files, as well as all other assets such as marker images, logos, etc. within the app, and not load them over the network.

If you do use remote URLs, you're actually loading over the network. This is slower than loading of them out of the apps own storage, relies upon the network being unavailable and sufficiently fast, and consumes network throughput and battery power that might better be spent elsewhere. It also slows down the startup time of your app, since the app won't really get started until it has downloaded the requisite files.

Just don't do it.

Minifying CSS and JS

Unlike a networked web browser on your PC, Cordova does not need to download the CSS and JavaScript files. And if your app is written loading CSS and JavaScript files over the network, you should definitely look at that and fix it!

As such, minifying or compressing these files does not make any sense. It may make your resulting app a few kilobytes smaller, but that really is irrelevant compared to the multi-megabyte size of even small apps. Balance that questionable gain against the overhead of compressing these files, and I find that it's totally not worthwhile.

Put <script> tags at the bottom of your HTML

With some specific recent applications that were rather intensive, I hit upon an interesting condition. When running the app on my iPad, it would fail to load - the framework would load up, HTML would display and style, ... then nothing. This would never happen. When I run it under an emulator, nor on older/slower devices, and never if I put in a blocking time delay such as a alert() call to slow it down.

Ultimately, the workaround was simply to move all of the script tags down to the bottom of my index.html file. This seems to affect the loading sequence in some way, as to avoid some sort of race condition in my iPad, but I couldn't characterize. Strange but true.

Downloaded Files and iCloud

If your app downloads and stores any files, such as map tiles for off-line use, or a JSON file database, then your app probably will not be accepted into the iOS App Store. This is because of a term, that apps may only store data specifically generated by the user, such as documents. It goes on to state that files that are automatically downloaded for off-line use, such as the map tiles and JSON database file, must be tagged, so as not to be backed up by iCloud.
 
Any directory or file that you create within your own code, you must use the setMetadata() call to tag it for not being backed up. This is done as follows:
file.setMetadata(null, null, { "com.apple.MobileBackup":1}); 
As you test your app, go into your iPads backup settings, and check the iCloud usage for your app. There will be a minimum of about 100 kB, for metadata files and the like, and that is acceptable. But if you see it storing more than that, look closer.

Low Ceilings

A high-end modern smart phone, can have 2 GB of RAM and two CPUs. But go back only two years, and things change somewhat. While an iPhone 5 can readily handle 150 relatively complicated trails being loaded from GeoJSON and laid out onto a Leaflet map as vectors, an iPhone 4S will crash the app trying.

It's important not to go overboard. Seemingly-small enhancements such as adding a glow effect, do cost CPU time and make rendering slower. Downloading a JSON database with thousands of records may not be a problem, but drawing all thousands of markers onto the map could be a problem same as on a PC... but perhaps with a lower ceiling that you don't notice when you do that very same data set on a PC.

The moral of the story, is simply to keep in mind that not everybody has a fancy cell phone like yours, and that you should be testing on lower-and hardware and emulators as well.



Tuesday, July 22, 2014

Mobile Development with Cordova (Phonegap): Chapter 7

Chapter 7: Beta Testers


Let's continue on with that default Cordova app, the one that does nothing except say Device Ready, and discuss how you'll work with beta testers. Again, your own programming style and needs will dictate how you program your app, and the real challenge is everything else: distribution, emulators, and so on.


So, beta testers. If someone wants to beta test an app, the techniques for Android and iOS are quite different.

Android

Simply get them the APK file through any convenient means. If the APK is small enough you can email it to them, but you can upload it to any convenient website, send it via Dropbox, etc.

When they open the APK, they will be prompted to install it. Easy.

Tip: Some Android phones have a default setting that they will not install any apps that do not come from the Market / Store. If the application will not install, they should check their Settings to see if this option is used.

Tip: If the digital signature has changed, and they're upgrading an existing app, they may need to uninstall the current one. This is why I always use the --release flag, it omits this accident.

iOS

An iOS device will only run an app, if the app's Provisioning Profile specifically mentions that device. Unless the specific iPhone, iPod, or iPad is already listed in the devices section, the device will refuse to run it. This means that you will need to:
  • get the beta tester's device ID (UDID) via iTunes
    This tutorial is helpful:  http://whatsmyudid.com/
  • enter it into the Devices list on the Apple portal
  • generate a new Provisioning Profile on the Apple portal
  • load the new Provisioning Profile into Xcode
    Xcode / Preferences / your identity / the reload button at the bottom
  • build the IPA using the Archive tool
Tip: Remember that all beta testers must be mentioned in the Devices and the Provisioning Profile. Remember that FFFF UDIDs are not valid, and as of iOS 7.1 many "find your UDID" apps now give inaccurate answers.
 
You cannot simply email the IPA file to the beta tester. 

iOS has a special technique called Over The Air (OTA) installation. If you have already created an OTA website for this app, you should be able to replace the IPA and have your beta testers hit it. If you're uploading a second copy with a special build/feature for somebody, then create a second manifest file and create a second hyperlink in your index.html file.

But if you've not yet created an OTA setup for your app, here's how:
  • Get a website that is hosted via SSL (https URLs).  Important: The URLs used in this process server MUST be via SSL (https) and the certificate must be a paid, signed certificate. Self-signed certificates will not work, and will give certificate errors. An expired certificate will also give errors.
  • Upload the IPA file to the webserver. You'll want to stick it into its own subfolder so you can have multiple builds, as well as the supporting files to facilitate the downloading process. Note the URL of the IPA file, and test it in the browser using an https URL to make sure it tries to download, e.g. https://www.example.com/mobileclients/democo/storeapp.ipa
  • Use this handy template and create a file named manifest.plist, uploaded into the same folder.
  •  Then use this handy template to create a file named index.html, uploaded into the same folder.
  • Make some edits to the manifest.plist file:
    - Line 14, the URL to the IPA file which you determined in step 1
    - Line 20, the reverse-domain name of the app, e.g. org.greeninfo.parkinfo
    - Line 22, the version number, e.g. 1.0.0
    - Line 26, the title, e.g. ParkInfo Mobile
  • Make some edits to the index.html file:
    - Line 7-8, the hyperlink and optional text; fix the URL to point at the manifest.plist file as per step 3
    - Your project likely won't distinguish Alpha from Beta; you probably only want one hyperlink at the moment
    - Then any other cosmetic, wording, link names, etc. that may inspire confidence in the beta testing technique such as the title
Beta testers should now be able to visit the website you just set up, and click the link to start installing the app on their iPad.

If the app won't install, there's only the one message that it couldn't be installed, which is not helpful. THere are a few things you can do:
  • Unzip the IPA file (it's actually a digitally signed ZIP file) and look through the contents.
    The embedded.mobileprovision file will have a list of certificates and devices.
    Check that the UDID really is on the list.
    Tip: It's digitally signed so has some binary crud, but your editor should still be able to open it.
  • Check their UDID again, and ask if they used an app or just copied down some number from their settings page. People really do resist plugging in iTunes, and will sometimes send multiple UDIDs trying various other strategies.
  • Check that the Provisioning Profile is not expired.
    They are only good for 6 months, and customers do tend to let projects slide for a while.
    If the PP is expired, generate a new one, load it into Xcode, and Archive and upload again.
  • Check the Build Settings for architectures.
    iPhones are usually arm7, arm7s, or arm64 and all architectures should be selected.
  • If you can get your hands onto the device for a little while, the best debugger is the Console, available via Xcode's Device Organizer when the device is connected via cable. The messages "cannot verify executable" and "MSIVerifySignatureAndCopy" indicate a signature issue.
    Unfortunately, this means that you must have physical possesssion of the phone while at your development Mac.

Friday, July 18, 2014

Mobile Development with Cordova (Phonegap): Chapters 5 and 6

Chapters 5 and 6: Running it, then Compiling APKs and IPAs


For the moment, let's forego developing the app and skip straight to running it and then compiling it. After all, what good is developing the app if you can't even run it for testing and hand it out to beta testers?


Plug in Your Hardware, Set up Emulators

iOS: Plug in that iPhone 4S and iPad you're using to test, and open the Xcode project file. In the upper-left you'll see a list of emulators and devices. When it's time to run your app, it's as simple as picking from this menu.

iOS: Look over the list of emulators, and  see if there are any missing that you would like. You may need to use Xcode/Preferences/Components to add some emulators, e.g. for testing iOS 7.0 for those folks who couldn't or didn't upgrade to 7.1

Android: Plug in your devices, then run adb devices from the command line. You should see your device listed, if USB Debugging is enabled on the device. Realistically, this almost never works and you'll spend time on Stackoverflow trying to figure out why. :)

Android: Run android from the command line to run the Android SDK manager. Install the necessary platform SDKs (e.g. Android 2.2 if you'll want to test there), then create emulators called Android Virtual Devices (ADVs).



Running it on Android


This should be as easy as:
    cordova prepare android
    cordova run android

The prepare step copies your www  into the target platform folder, where it will be bundled and run. Don't skip this step, or you'll find yourself running older code.

If you have a hardware device attached, it should be used automatically: the app will be injected onto it, and it should even launch automagically. Super convenient.

If you have no hardware attached, the platform will start up an emulator for you if you defined one. (this is mentioned above and also in Chapter 1, Android Virtual Devices or ADVs) If you already have an emulator running, that one will be reused.

To specify a device, give a --target parameter to the cordova run command, like this:
    cordova run android --target=ABC123456

Tip: To see what devices you have attached, run:
    adb devices
 If your device isn't listed, check out Google because that's a very well known and widespread phenomenon. Usually you just forgot to enable USB debugging, but some hardware just isn't gonna work. See chapter 2 where we set up your build environment and test it, for some tips.

In reality, I've had show-stopping problems with running the app on Android:

- The emulators take several minutes to load, if they happen at all. When they do, the app may or may not be there. As such, I've given up on the emulators.

- Some hardware devices are never detected via adb devices and therefore cordova run android doesn't detect them. In particular was my LG Spectrum, which would about 1 time in 50 be detected by adb devices but then disappear again. Eventually I went to Fry's and hit up Groupon, and got a Blu brand phone for $60 and a Nexus tablet for $100, and both of them worked fine. Moral of the story: the problem may be the device.

In the worst of times, my process for Android devolved back to old-school techniques: I compile the APK, then email it or upload it, so I can download it on my phone and install it. This is less than ideal, but if adb doesn't see it, not a lot I can do.


Running it on iOS

In Xcode with the project open, look in the upper-left. You'll see a list of devices, some of them your attached devices and some of them emulators. Select the one you like, then go to Project/Run.

Simple and slick.

Tip: You can terminate the app with Project/Stop.

Tip: You need a Provisioning Profile to distribute your app to other devices, but if you're using emulators and cable-attached devices, you can skip it for now.

Building an APK for Distribution (Android)

To compile an APK for Android:
    cordova build android --release

The resulting APK for Android will be in platforms/android/ant-build

You can submit this to the app store, hand it to your friends, etc. You can ship it on an SD card, email it, whatever.

Tip: Some versions of Android refuse to install an APK unless it comes from the authorized Store. If someone's trying to beta test and hits upon this, visit the Settings panel and see about enabling non-Store applications.


Tip: I prefer to always use the --release flag. It prompts me for the password (once for the keystore, then again for the specific key) but that's okay. The resulting APK will be useful to anybody who tries it. I know that if I get distracted I may generate a non-signed APK that only works for me, then hand that out to beta testers whose phones will refuse to install it.

Building an IPA for Distribution (iOS)

Load up the Xcode project. Hit up Project / Run which tries to run your app. It will run it on whichever device is displayed in the upper-left, be it an emulator or a real device.

Also in the Project menu is the Archive option. If it's greyed out, select a hardware device in the upper-left for running your app. You must have a hardware device attached and selected, for the Archive option to become enabled. Select the Archive option.

You'll be asked to choose a provisioning profile. Select whichever one you generated for Ad Hoc uses. (See Appendix D where I describe generating provisioning profiles)

Finally, the IPA file will be created for you, and is ready to hand out to your beta testers.


Monday, July 14, 2014

Mobile Development with Cordova (Phonegap): Chapter 4

Chapter 4: Stuff We Always Do


This article describes several tasks that we do on every single application, and which you will likely do as well. Consider it a continuation of Chapter 3 where we created a project.

Plugins

We tend to develop for the same platforms every time, and there's a certain subset of plugins that we use in every single project.

cordova platform add ios
cordova platform add android
cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.file-transfer
cordova plugin add org.apache.cordova.geolocation
cordova plugin add org.apache.cordova.network-information
cordova plugin add org.apache.cordova.splashscreen

Tip: The console plugin allows console.log() to log to the app console, which is useful in iOS when you have the device attached via cable. I don't use it much, though, since most of my development and debugging is via weinre.

Tip: The vibration plugin breaks the app compilation on iOS. Don't bother.


Xcode Setup: iOS

Open the project's xcodeproj file, located under platforms/ios This will launch Xcode.

Select the project (left sidebar, make sure the folder icon is picked, then the project is the first item on the list) then the Info settings.

Deployment Info:
  • Select yourself as the Team.
  • Select appropriate entries for Device Orientation, typically all 4.
  • For Status Bar Style, select Hide During Application Launch.

Info:
  • Custom iOS Target Properties:
  • Status Bar is initially hidden: Set to YES
  • View controller-based status bar: Set to NO

Icons and Splash Screens: Android

Tip: See also http://cordova.apache.org/docs/en/edge/config_ref_images.md.html

Look in platform/android/res and you'll find drawable folders for various screen resolutions (e.g. drawables-xhdpi), plus the default with no specific resolution (drawables).

Swap in the icons with new PNGs.
These PNGs should be RGBA (24-bit plus alpha channel) and the vogue these days is rounded corners.
The sizes of these PNGs are as follows:

default -- 32 x 32
ldpi -- 32 x 32
mdpi -- 48 x 48
hdpi -- 72 x 72
xhdpi -- 96 x 96
xxhdpi -- 144 x 144

You can also place an image named splash.png into each of these subfolders too, and it will act as the splash screen as the app starts and loads. These should be high quality PNGs, of the following sizes:

ldpi -- 426 x 320
mdpi -- 470 x 320
hdpi -- 640 x 480
xhdpi -- 960 x 720
xxhdpi -- 1410 x 960

Edit config.xml and add these two lines, to show the splash screen for 3 seconds (3000 ms).

<preference name="SplashScreen" value="screen" />
<preference name="SplashScreenDelay" value="10000" />

Lastly, you may need to do a clean in order to have the new versions detected:
./platforms/android/cordova/clean

Tip: The splash screen time stated in the config.xml should be the maximum before the platform hides it, but your app can hide it whenever it's ready. Good practice is to explicitly call navigator.splashscreen.hide() in your program during the onDeviceReady event handler, so it doesn't keep showing the splash screen any longer than necessary.

Icons and Splash Screens: iOS

Look in platforms/ios/PROJECTNAME/Resources and you'll see the icons and splash folders.

Just start replacing images with your own. For the splash screens they should simply be high-quality RGB PNGs, while icons are high-quality PNGs with alpha channel (RGBA) and rounded corners.

splash/Default-568h@2x~iphone.png   640x1136
splash/Default-Landscape@2x~ipad.png   2048x1496
splash/Default-Landscape~ipad.png   1024x748
splash/Default-Portrait@2x~ipad.png   1536x2008
splash/Default-Portrait~ipad.png   768x1004
splash/Default@2x~iphone.png   640x960
splash/Default~iphone.png   320x480

icons/icon.png             57 x 57 
icons/icon@2x.png          114 x 114 
icons/icon-40.png          40 x 40 
icons/icon-40@2x.png       80 x 80 
icons/icon-50.png          50 x 50 
icons/icon-50@2x.png       100 x 100 
icons/icon-60.png          60 x 60 
icons/icon-60@2x.png       120 x 120 
icons/icon-72.png          72 x 72 
icons/icon-72@2x.png       144 x 144 
icons/icon-76.png          76 x 76 
icons/icon-76@2x.png       152 x 152 
icons/icon-small.png       29 x 29 
icons/icon-small@2x.png    58 x 58 

Lastly, you may need to do a clean in order to have the new versions detected:
./platforms/ios/cordova/clean

iOS: Disable Cloud Storage

Our apps tend to be based on maps, and on storing map tiles. Apple terms allows only user-generated documents to be backed up, and require that we disable the automated backup of map tiles (as well as downloaded database files, LocalStorage and WebSQL content, etc). However, Cordova only allows us to turn backups on and off globally; we cannot pick and choose that some files are backed up. So, disable the cloud backup as follows:

- Open up platforms/ios/APPNAME/config.xml
- Look for the key BackupWebStorage
- Change it from cloud to none


Android: Allow App to Resume

Problem: By default, Android apps will run a new instance whenever you open it. If you open the app and get it into some state (say a search has been performed, your map centered), then switch to some other app (e.g. check your text messages), then come back... you start the app over again, complete bwith splash screen, losing your previous state. That's a useless app!

Solution: Change a default setting in the Android Manifest file, stating a "single task" launchMode.

  • Edit the file platforms/android/AndroidManifest.xml
  • Look for the <Activity> declaration, which you'll see also defines other params about your app, e.g. android:name="YourAppName"
  • Add this attribute:   android:launchMode="singleTop"
Now (after a rebuild) the Android app will behave in the proper way and will resume when you come back to it, without losing your place.  (and why this isn't the default we'll never know)



Thursday, July 10, 2014

Mobile Development with Cordova (Phonegap): Chapter 3

Chapter 3: Creating Your Project

Creating the Empty Project

Open a Terminal, and "mkdir" and "cd" your way into a folder where you'll want to start placing your projects. For me, I created a "Mobile Projects" folder underneath my home folder.

This command boostraps your app, copying in some template files for a very Hello, Cordova sort of app:
    cordova create exampledir biz.example.firstapp "Example Application"

The 3 parameters are:
- the name of the folder to create, e.g. exampledir will be the name of the folder
- the application name in "reverse DNS" convention, e.g. org.greeninfo.myfirstapp
- The name of the app itself as it will be named in the store and on the device, e.g. include spaces but not version numbers, and keep it brief and snazzy

Tip: It's very tedious to change the name of an app after it has gotten underway, so you really need to get this right the first time. Yes, really. Just like in that Dilbert episode.

There's a certain list of platforms and plugins that we will always use (Android and iOS, File access, FileTransfer, Network Status, etc.) so let's just get them out of the way now:

    cd exampledir
    cordova platform add ios
    cordova platform add android
    cordova plugin add org.apache.cordova.file
    cordova plugin add org.apache.cordova.file-transfer
    cordova plugin add org.apache.cordova.geolocation
    cordova plugin add org.apache.cordova.network-information

You should get familiar with the cordova command-line utility, as well as what plugins exist. In Cordova 3, virtually everything is implemented as a plugin.

A Quick Rundown

This is a brief overview of some of the files and folders. There's a lot more that I can't cover in detail here, just some highlights:

www
This folder houses your HTML, JavaScript, and CSS. This is where you'll do 99% of your work.

config.xml
This provides build options and metadata about your app. You will definitely want to edit this, especially to set the author attribution, the app description and name, and so on.

platforms/ios/ProjectName.xcodeproj
This is the Xcode project file (actually a folder, but OS X treats it specially). Open this to set special iOS-specific settings, such as hiding the status bar. This will be covered in a different article, where we describe tips and tricks for doing the actual programming.

platforms/ios/ProjectName/Resources
For the iOS platform, this stores additional assets such as icons and splash screens.

platforms/android/ant.properties
This configuration file will be used by ant when compiling the Android version of the app. This file does not exist by default, and is covered in more detail in a different article.

platforms/android/res
For the Android platform, this stores additional assets such as icons and splash screens.

platforms/android/assets/www
platforms/ios/www
These folders hold a temporary copy of your www folder content. This is used during the build process. It is not necessary to edit these copies in addition to the main www folder; they are automated copies.

Setting Up Certificates (iOS, Xcode)

Remember, the key store and certificates and provisioning profiles you set up a long time ago? Let's go ahead and configure these utilities to use them, signing your app with the keystore (Android) or Provisioning Profile (IOS).

In Finder open up your project folder, then open up two files, one for iOS and one for Android.

Android:
Start by creating a file under your project platforms/android folder, named ant.properties
It should have these two lines, of course customized to the keystore you generated earlier:
    key.store=/users/USERNAME/android.keystore
    key.alias=keystorealias

Tip: Every time you use cordova run android --device it will prompt for the passphrase. This is a little annoying, but not very compared to some of the problems you'll have. :-) For myself, I prefer to have my APKs always signed so I don't run into problems later, when I forget to sign a build, or send someone an unsigned APK.

iOS:
Open platforms/ios/PROJECTNAME.xcodeproj This will open Xcode.

Select the project itself (probably the first item on the upper-left panel) and set some project properties, most notably the Team. When you select a Team you'll be prompted to enter an Apple identity; it will then download a certificate and provisioning profile for you, saving them into the application's Xcode settings.

Run It On Emulators

Let's start by running the Hello Cordova app on iOS and Android emulators. If you won't be using emulators, I suppose you can skip this step.

The Cordova CLI apps make it pretty easy to start up the app in an Android or iOS emulator:
    cordova emulate android
    cordova emulate ios

A poorly-documented feature, is that you can specify the device for testing: iPad, iPhone 4, etc. with the --target parameter.
    cordova emulate ios --target="ipad (retina)"

For iOS there's a specific list and you may find this set of aliases quite handy. Add these to your .bash_profile and start a new Terminal, and your emulation commands will be quite simple:
alias emipad='cordova emulate ios --target="ipad (retina)"'
alias emiphone3='cordova emulate ios --target="iphone (retina 3.5-inch)"'
alias emiphone4='cordova emulate ios --target="iphone (retina 4-inch)"'
alias emiphone='cordova emulate ios --target="iphone"'

For Android, target names are the names of AVDs (as listed in adb devices) and you can make up a similar set of "emulate android" aliases for your particular AVDs and devices.

Run It On Hardware: iOS

First, plug your iPad into your Mac. You may be prompted as to whether the iPad should trust this computer, allowing the computer to inject applications onto it, etc. Naturally, you should accept.

Refresh the iOS platform directory which will form the app:
    cordova prepare ios
If you skip this step, you'll be running an older version of your app, and that can get confusing if you're  debugging something not visually obvious.

Then in Xcode, look in the upper-left where you'll see a list of platforms, e.g. iPhone Retina 3.5" Select your hardware device from the list. Now go to Product / Run  This will compile the app and then inject it onto your iPad and then launch it. Very simple and reliable.

Tip: Every time I plug in my iPad or Android, a photo application pops up. I don't know that there is any way to stop this, and it's very annoying.

Run It On Hardware: Android (ADB)

Make sure that your Android device has "USB Debugging" enabled. This is buried in your Settings panel, in a submenu called Developer Options. Then plug your tablet into the Mac's USB port, and the Android should report "USB Debugging Connected" at the same time as it does its usual USB behavior (offering to enable SD card sharing, or to Charge Only).

On the Mac, in a Terminal, you should be able to see the device when you run adb devices
Your device has an ID that may or may not be intuitive, may or may not contain the manufacturer name. But, that's the ID# and it'll stay the same for that device.

You should now be able to cordova run android --target=ABC123456 and have the app run on that specified device. Again, see adb devices for the listing. This does allow you to run on multiple Android devices simultaneously.

If your device doesn't show in adb devices, then fuss with it a bit:
- Unplug it and plug it back in.
- While leaving it plugged in, toggle USB Debugging off and on.
- Unplug it and plug it back in. (again)
- Try another USB cable. (some low quality cables have issues)
- Try another USB port. (nobody knows why)
- Try connecting directly to the computer's USB port instead of to the USB hub. (some hubs lose enough power that USB Debugging malfunctions)
- Try another device.

Tip: On some devices such as my LG SPectrum, it's so flaky that I gave up completely on using adb. I use the other technique described next. But I went to Fry's and bought a $60 Blu brand phone, and it works perfectly with adb.

Run It On Hardware: Android (Manual Copy, Slow But Works)

Compile the Android app, forming an APK file:
    cordova build android --release

The resulting APK is in  platform/android/ant-build

Plug in your Android to the Mac, and turn on USB Storage mode. On the Mac, copy the APK file onto the Android, eject the Android device, turn off USB Storage, and install the APK by opening it.

Tip: Android 4.x has App Installer, which makes short work of finding and installing the APK. It will scan local storage, find all APK files, and present you with a list. Three taps and you're testing.

Now Get Hacking !

If everything has worked out so far, then you're ready to start actually writing your own application. Start replacing content in the www  folder, installing plug-ins, making adjustments to config.xml, and figuring out the myriad problems involved in any complicated app. :-)

Monday, July 7, 2014

Mobile Development with Cordova (Phonegap): Chapter 2

Chapter 2: Setting up Your Build Environment


Overview of Components

The Android SDK works well with the Eclipse IDE. This doesn't mean that you need to use Eclipse to type out your code, but if you run into trouble you may be glad you have installed, since other peoples' documentation and procedures will refer to Eclipse and the Android SDK.

The Xcode IDE for OSX is required to "compile" your Cordova project. You won't use the GUI much, but you will definitely use the command-line tools. You will use the GUI a little bit, though, for example making edits to the app settings to hide the status bar.

As such, we will be installing both of these tools in addition to the Cordova software itself.

Installation and upgrading of Cordova, is best done through NodeJS, so we will install that as well so that we can install the Cordova library.

Cordova is built on Java, and therefore the build process depends on having the JDK installed and not simply the JRE.

Lastly, the build process for Android requires Apache Ant, so we'll install that too.

A final note: Much of what we do here will be command-line-based within the Terminal application on your Mac. As such, you should just get used to it, and may find it useful to drag Terminal into your Dock.


Installation: Eclipse and Xcode

Eclipse can be downloaded here http://www.eclipse.org/downloads/
It simply unzips, then you run Eclipse from the resulting folder. I like to move the Eclipse folder into my Applications folder, then drag the executable into my Dock so the folder is out of the way but the application is readily accessible.

Use the App Store to install Xcode
Then, install the Xcode command-line tools:
    - open Xcode, go into Xcode / Preferences / Components
    -  Select the CLI Tools, and appropriate iOS simulators as far back as you want to go (7.1 is out, I went back to 6)

Xcode has one more step: Acknowledging the license. This is done via CLI.
    sudo xcodebuild -license

Installation: Java

In the Terminal type:
    javac

If you have the JDK installed this gives some instructions on how to use javac, and your JDK is already installed.

If not, then it will fail but OSX will recognize the command as belonging to the JDK package, and you'll be prompted to install the JDK/JRE. Neat, huh? Go for it.

After it has installed, there's still a step. The build tools will need the JAVA_HOME environment variable set.
    Edit the file ~/.bash_profile   (it may not exist yet, create it)
    Add this one line:
        export JAVA_HOME=$(/usr/libexec/java_home)

Installation: NodeJS

The npm utility is part of NodeJS, and is effectively your package manager as far as Cordova is concerned.

Visit http://nodejs.org/download/ and download the DMG file for OSX. Run it, and follow the installer. Simple.

Then let's install the Cordova library, as well as an Android debugging tool:

    sudo npm install -g cordova
    sudo npm install -g adb


Installation: Android SDK and Android Development Tools (ADT) and the Eclipse Plugin

Fire up Eclipse, and install the Android Development Tools (ADT) plugin.
Go to Help / Install New Software
Enter this for the repository:  https://dl-ssl.google.com/android/eclipse/

Eclipse will restart, and will ask for the location of the Android SDK -- but will also allow you to let it download one. (Note that older documentation has you download the SDK separately, but this is no longer necessary.) It will download the SDK tools (including the "android" configuration program which you'll use a lot) into /users/YOURNAME/android-sdks

After it comes back up, add the ADT tools to your PATH so you can use them in the terminal:
    sudo nano /etc/paths
Add these three lines:
    /users/YOURNAME/android-sdks/tools
    /users/YOURNAME/android-sdks/build-tools
    /users/YOURNAME/android-sdks/platform-tools

You should now be able to start a new Terminal window, and run the command android and get the ADT configuration tool.
You'll be seeing a lot of this later on, as you install more Android SDK components.

Your first task will be to install a bunch of SDKs for various versions of Android, as well as the HAXM.
Go ahead and run android, then install the following:
    Android SDK Tools
    Android SDK Platform Tools
    Android SDK Build Tools
    Android 4.4 SDK Platform and Intel Atom System Image
    Android 4.2 SDK Platform and Intel Atom System Image
    Android 4.1 SDK Platform and Intel Atom System Image
    Android 2.3 SDK Platform and System Image
    Extras: Intel x86 Emulator Accelerator (HAXM)


A Brief Word on Android Emulators and HAXM

If you want to test on a plethora of Android devices, you'll usually want to use the Android emulators and Android Virtual Devices (AVDs). These are exactly what they sound like: virtual machines running Android, so you can test your apps without buying the real devices.

Android emulators are painfully slow, but Intel Hardware Accelerated Execution Manager (HAXM) helps. You downloaded the HAXM earlier, but it didn't in fact install it. Installation of HAXM is done via Finder and not via CLI (it's an OSX installer, and not a command-line tool you'll use again). Use Finder and browse to your home folder, the android-sdks subfolder, then extras, and the Intel  Hardware Accelerated Execution Manager (HAXM) and open up IntelHAXM.dmg  This is a regular installer, a few click and you're done.

Tip: Some older android emulators will not run on an Intel CPU, but ARM. These will be even slower than the Intel ones because they cannot use HAXM. Even the Intel ones are painfully slow, and have trouble with actually installing the APK. For myself, I prefer to just buy the $60 tablet at Rite Aid, and a $100 Nexus tablet via Groupon, rather than wait several minutes at a time for an emulator that may or may not start successfully.

If you do choose to use emulators, they are called Android Virtual Devices (AVDs). These are managed in the android manager, under Manage AVDs. The options should be self-explanatory, such as the screen size and the storage, and there are a bunch of presets for some popular devices.

Installation: iOS simulators

Pretty simple, really:

    sudo npm install -g ios-sim
    sudo npm install -g ios-deploy

Tip: As with the Android emulators, the iOS emulators are quite slow and don't always load your package anyway. Since we need to test on real hardware anyway, I prefer to just test it there.


Ready?

By this time you should be able to execute the following commands in the Terminal, and at least have them show some help messages, or at least error messages indicating that they are installed.
    ant
    javac
    echo $JAVA_HOME
    adb
    cordova
    ios-sim

At this point, you're ready to begin creating your first project!

Saturday, July 5, 2014

Mobile Development with Cordova (Phonegap): Chapter 1

Chapter 1: Buying a Mac, buying an Android, then Getting Your Certificates Ready

Apps are digitally signed in order to verify that they come from the stated author. The paradigm of digital signatures is different between Android and iOS.

On iOS,  you must have an Apple developer account. An app is signed with your certificate, and Apple has your identity and credit card on file, so one could trace responsibility and ownership for an app back to the owner. And since the owner signed the app, they can hypothetically be held responsible for the app's content and behavior.

Android apps can be signed with any certificate, including self-generated self-signed certificates. These certificates can be generated at will. The signature of an app is used to verify that this app really does come from the same publisher. For instance, someone can create a Google Play developer account named "Green Info" and an app named ParkInfo Mobile and hope to fool users into thinking it's GreenInfo Network's ParkInfo Mobile app -- but if they try to upgrade to this fake app, the apps will have the same name but different signatures and the OS will refuse to install this fake upgrade.

As such, the very first step in developing mobile apps, is to generate the certificates which you will use to sign your Android apps, and signing up for an Apple Developer account for your iOS apps.

Buy a Mac

The development tools to build the app for iOS, are available only on OSX. While a Windows or Linux PC could build for Android, you still need a Mac to build for iOS, so you may as well embrace this and buy the Mac. Fortunately it only needs to run Mountain Lion or later, and there's no heavy code-crunching going on within Cordova, so a low-price used laptop off eBay should do you just fine.

Unless... If you intend to run the iOS emulators, you need all the CPU power and RAM you can afford. You also need an HD monitor; lower-resolution monitors will display the app strangely, since modern phones have better resolution than older monitors. For myself, I prefer to forgo the emulators and buy the iPad and iPhone and test on real hardware, since that costs less than a new Mac anyway.

Tip: To submit an app to the App Store you must have screenshots from an iPad, a 3.5" Retina iPhone, and a 4" Retina iPhone. This means that you must own all of these devices, and/or have beta testers who can take screen shots on these devices.

Android

For Android, the process is fairly straightforward: you generate a certificate yourself, and be sure to sign your APK files with the same certificate every time. As such, each version of the APK is assured to have come from the same author.

There is no central authority for these certificates, as the goal is simply to prove that the app comes from the same author, and not necessarily to tie the certificate to your personal identity.

There is a separate article dedicated to generating these "keystore" files.


Apple & iOS

For iOS, the situation is much more complex. You need to sign up at the Apple Developer website and pay a fee of $99 per year. You then need to define a certificate and a "provisioning profile" A provisioning profile is a combination of your Certificate, a selection of Application IDs (in case your company generates different types of applications with different teams.), a selection of devices (e.g. "these specific 5 iPads and 2 iPhones", or else "for public release") and additional Apple services and features (whether it uses their payment system, etc).

There is a separate article on how to generate certificates, and how to update Provisioning Profiles. You'll do this particularly when someone else wants to test out an app, and you'll need to add them to the device list and then build a new Provisioning Profile. But, you can at least run  the app on your own cable-attached device without generating a Provisioning Profile.


Buy your test hardware (or set up emulators)

You can test on hardware and on emulators.

Android emulators (Android Virtual Devices, AVDs) are set up via the android management application, which we discuss later when setting up the SDK. You'll want to create one with an old enough OS and low enough specs, that our testing will be applicable to trailing-edge phones.

For myself, I've had no good luck with the emulators. They may or may not, and if they do it's after several minutes, and they rarely have my app on them when they do start. Not wholly useful.

Android hardware comes in all sizes and prices. For $60 you can buy a crummy Craig tablet at Rite Aid or CVS pharmacies, and Nexus tablets showed up on Groupon for $110 a few weeks ago. I prefer to test on hardware, rather than deal with the buggy time-consuming emulators.

iOS emulators are much nicer. These are all built into Xcode: after you load your project, look in the upper-left to choose which device you want to use. If you have a hardware device attached (an iPad, an iPhone) you can select it from the menu as well. As such, there is no separate step for running your app on hardware iOS or emulated iOS.


Tuesday, July 1, 2014

Mobile Development with Cordova (Phonegap): Preface

Thanks a million to GreenInfo Network, my employer who has funded this time to write out what I've learnedand then to share it with you. Cordova takes a lot of the tough part out of mobile development, allowing you to program a phone like a browser.

There are plenty of books out there on the topic, but none of them that I've read have covered the whole process in detail. There are whole chapters on JavaScript's if and switch and function statements, but nothing about how to sign your APK or archive and sign an IPA file; whole chapters on what a hybrid app is, but no mention of the Apple Store refusing to approve an app unless you set the Don't Back Up metadatum on downloaded JSON files.

So, here it is: 14 chapters based on our real-world experience. It'll be a bit light on "How to program in JavaScript" because that's your problrm, but it will cover the dirty topics nobody else has touched.

Mobile Development with Cordova (Phonegap): Glossary

Chapter 0: Mobile Development Glossary

Before I get started, I want to define a few terms. This also acts as a brief introduction to the concepts: that you need a provisioning profile to work on iOS, that you sign apps, etc.

Hybrid App
This is what you'll write with Cordova. It's not a truly native app written in Java (Android) and Objective C (iOS) but is basically a web application with a self-contained browser. It has an icon and is in the store, so it acts like a native app, but it's not really written in the same way.

Cordova / PhoneGap
Cordova is essentially an embedded browser which launches as an app. The upshot is that you can write CSS/HTML/JavaScript and it will be interpreted in this browser. Unlike traditional web browsers, the Cordova browser has additional functionality such as accessing the accelerometer, compass, GPS, camera, and filesystem (SD card). PhoneGap is a Adobe's name for the project and their commercial offerings such as Phonegap Build, while Cordova is the name of the open-source project over at Apache. The documentation at PhoneGap.com applies to Cordova, and the two terms are used practically interchangeably.

Digital Signature
A cryptographic process by which a file is "signed" based on a "certificate" A digital signature is infeasible to forge, so a matching signature is presumptive evidence that  the file is signed by the person who owns the certificate. Digital signatures are used to verify that two apps came from the same author, most notably if a new app claims to be an upgrade of a pre-existing app. If the signatures do not match, then the second is presumed to be fake and will not be installed.

Digital Certificate
A certificate is a cryptographically-strong set of numbers, used for encryption and digital signatures. A certificate consists of two parts: a public part (given out to the public, the visible certificate) and a secret part (the key). A signature can be verified using only the public part of the certificate, while a signature may only be generated using the secret part of the certificate. A digital certificate can be "issued" by a signing authority (Apple for iOS apps, GoDaddy for website SSL certificates), or a person can generate their own "self-signed" certificate for personal or internal use. Apple issues certificates to developers, while android allows you to generate your own self-signed certificates.

Xcode
An integrated development environment (IDE) for OSX. It is used to compile Cordova apps for iOS, as well as for making changes to the build settings, e.g. whether the status bar should remain visible. Xcode consists of the GUI tools, as well as a set of command-line apps. For the most part, I use Xcode to run my apps on the iPad and iOS emulators, then to archive the package to an IPA and sign it, but I don't use it as my text editor.


Eclipse
An integrated development environment (IDE) that runs on Windows, OSX, and others. A very popular alternative to a simple text editor. I myself don't use Eclipse, but a lot of people do.

Developer Certificate
A digital certificate generated by Apple for the purpose of identifying a specific Apple developer. An Apple developer may have more than one certificate. These are generated at Apple's developer portal, and Xcode has a facility to download them and to allow you to select which on you'll use to sign your programs.

Development certificate / Distribution certificate
Digital certificates issued by Apple, used to sign apps. An app signed with a development certificate can only run on devices registered to that same developer. An app signed with a distribution certificate, is suitable for deployment to other devices and to the App Store. An Ad Hoc certificate is a type of Distribution certificate, and is described below. These are generated via Apple's developer portal, and Xcode has facilities to import them from your developer account.

Provisioning Profile
A statement from Apple that a given combination of Developer Certificate, Application IDs, and Device IDs, is allowed to run this app. This is particularly relevant when using Ad Hoc Distribution, as the app will only run for the Device IDs specified in the Provisioning Profile. These are generated via Apple's developer portal, and Xcode has a facility to download them from your developer account. When you "archive" your app to generate an IPA file, you'll be asked to choose a Provisioning Profile to sign the resulting IPA. Note that you'll have separate Provisioning Profiles for posting an app to the store versus handing it out for Ad Hoc beta testing.

Ad Hoc Distribution
Distribution of an app without the Store and its approval process, usually intended for beta testing and limited distribution. An Ad Hoc Provisioning Profile would be created, listing the specific applications and devices allowed. Note that an Apple developer account can only have 100 devices listed, and can only change this list at the beginning of each calendar year. Thus, Ad Hoc Distribution is not necessarily suitable for distribution to an entire organization, especially if you're a contracting house with numerous clients: 5-10 testers per client can exhaust 100 slots quickly. Further, the Apple developer is only allowed to register devices of the same model as devices they already own (the developer must have an iPod registered in their name, in order to add an iPod to the device list for Ad Hoc Distribution).

Keystore
For Android platforms, multiple digital certificates may be combined into a single file called a keystore. Each certificate within a keystore, has an alias identifying that key within the keystore. Typically, a keystore is encrypted with a password, and certificates within the keystore may also be individually encrypted with their own passwords. In order to uniquely identify and use a given certificate, the alias of the certificate must be known, as well as the password to the keystore, as well as the password to the individual certificate.


Keychain Access
A program on OSX for generating digital certificates. It can also convert them, import them from Apple's website, etc.

adb
Android Debugging Bridge. This command-line tool communicates with attached Android devices over the USB, and can load software into them, reboot them, and so on. The command adb devices will come up often, as it's used to show a list of attached Android devices... which is how you verify that your device is attached and can be used to run and test your app.

USB Debugging Mode
On Android, this is a special setting that enables the USB connection to be used for that stuff described in adb above. To use your Android device via adb, you absolutely must have USB Debugging Mode enabled.

Android SDK
The Android Software Development Kit (SDK) is a collection of software and libraries allowing you to compile apps for Android, and allowing your Mac to communicate with Android devices via adb. This includes Android OS images and emulators, and API libraries.