WKWebView, WebAudio and PhoneGap for iOS games

Here’s a handy little tip for anyone wanting to load files via AJAX in their PhoneGap apps that run on iOS courtesy of PhoneGap.

Our first attempts at creating games with PhoneGap were satisfactory but not brilliant. The frame rates were awful though the music and sound effects seemed to work fine. So we did a little digging and found that by default PhoneGap will use UIWebView, the default web view, on iOS.

You can change this to use the far more advanced and polished WKWebView (Web Kit Web View) which makes great use of such things as requestAnimationFrame. Something that is hopefully familiar to HTML5 game developers.
With WKWebView you also get to run against the superior JavaScript Nitro Engine which will massively increase the performance of your games.

Here’s how to implement WKWebView via your config.xml.

Add the following just beneath your <widget> declaration:

 <feature name="CDVWKWebViewEngine">
 <param name="ios-package" value="CDVWKWebViewEngine" />
 </feature>
 <preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />

 

But we found that our audio now failed to load.

We use AJAX (XMLHttpRequest) to load our audio. To date it’s worked a treat. The reason we use it is because it’s a neat way to asynchronously load and capture the onload event and act upon it as we configure each audio file (volume, for example).

This works using a relative path.

Here’s some code:

 var request = new XMLHttpRequest();
 var url = "sfx/" + o.soundname + "." + AUDIOFORMAT;
 request.open('GET', url, true);
 request.responseType = 'arraybuffer';

You can see that our mp3 files are sat in a sub-directory called /sfx.

But WKWebView doesn’t like this. It wants its AJAX calls to be fully qualified from the http://

The change to the config.xml file is simple.

Add the following amongst your plugin declarations:

<plugin name="cordova-plugin-wkwebview-engine-localhost" spec="https://github.com/apache/cordova-plugins.git#wkwebview-engine-localhost" />

And change your content definition from

<content src="index.html" />

to

<content src="http://localhost" />

Hope that helps somebody!