Porting the Bubblewrap Web App to Google Android* and Apple iOS* using PhoneGap* compatible API

Bubblewrap is a game where the user pops bubbles. This article describes porting the original Tizen BubbleWrap game to use Adobe PhoneGap* so it runs on Google Android* and Apple iOS* mobile devices.

The source code for this sample can be found here: https://github.com/gomobile/sample-bubblewrap.


  • Convert it into an Android and iOS app using PhoneGap Build and the Apache Cordova* APIs.
  • Correct/fix the app so it works well in browsers and on devices.
  • Show bubbles of the same size on different devices but the number of bubbles displayed depends on the screen size.

Initial State

To begin, I downloaded the application from the original Tizen location and tried it in a mobile device browser. It worked fine in landscape orientation but when rotated 90 degrees (portrait orientation) the game was impossible to play. For example, a screen shot in landscape orientation:

and when rotated to run in portrait orientation:

I built this app with PhoneGap Build and tried it on multiple devices. On Android 4 and iOS 5.1 I encountered two problems: no sound and the software license page did not display. On Android 2.3 the situation worsened, in addition to the Android 4 problems, the application did not scale properly and did not fit the screen -- it was impossible to play the game on an Android 2.3 device.

Porting Solutions

Cordova APIs

I first added Cordova (formerly PhoneGap) API support for playing sound on the devices:

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {


  window.onblur = function() {infocus = false;};
  window.onfocus = function() {infocus = true;};

The Cordova function to load media files:

function playMusic(soundPath){ 
  if (window.device)              // if Cordova/PhoneGap is used: 
    var path = getPhoneGapPath(); // path to phonegap 
    path = path+soundPath;        // path to the media file 
    var media = new Media( path, mediaCallSuccess, mediaCallError ); 
    new Audio(path).play(); 

Also, I changed the format of sound files from .ogg to .mp3 for iOS support.

License Loading

I made some changes to the license loading process. The original Bubblewrap app uses a frame to load the software license text, but this method is not supported by Cordova. Instead, I used the following code for running on mobile devices:

if (window.device) {   // running in PhoneGap
  var readRequest = new XMLHttpRequest();
  readRequest.open("GET", licFname);
  readRequest.onreadystatechange = function () {  // call when state changes
    if (readRequest.readyState == 4 && readRequest.status == 200) {
      var divLicense = document.getElementById("licensetext");
      divLicense.innerText = readRequest.responseText;

Image Sizes

In the original application, all images are specified in pixels. Thus, I decided to use the CSS transform functions scale and translate to modify image sizes as a function of screen size. Upon further testing I found a scaling issue on Android 2.3 that caused a problem with this strategy: the translate function works but the scale function is ignored (http://code.google.com/p/android/issues/detail?id=12451). The solution was to change absolute sizes to relative percentages of X.

According to the requirements, the size of the bubbles should appear approximately the same on all devices, which meant that the number of bubbles needed to adapt dynamically to fill the available screen space. To do this, the size of playview (the bubble container) is fixed and does not change, even if the browser window is resized. I revised CSS sizes from using absolute pixels to using percentages, but set the size of playview in absolute pixels, using JavaScript, as a function of the screen size:

var screen_height = $(window).height();
var screen_width = $(window).width();
$('#playView').css('height', (screen_height*view_k) + 'px');
$('#playView').css('width', (screen_width*view_k) + 'px');

Now that the size of the playview container is known I can generate the bubbles. First, the number of bubbles is calculated:

var x_bubbles = (width-width%bubble_size)/bubble_size;   // num of bubbles on x axis
var y_bubbles = (height-height%bubble_size)/bubble_size; // num of bubbles on y axis

where width is the width of bubblesheet (it is calculated as a function of the playview size) and bubble_size is a constant. Then a list of bubbles plus intermediate spacers can be generated and added to the bubblesheet using the JavaScript appendChild function:

for(var i = 0; i<y_bubbles; i++){
  var hbox = document.createElement("div");
  hbox.className = "hbox";
  var bubblegap = document.createElement("div");
  if (i % 2 == 0) {
    bubblegap.className = "bubblegap-odd";
  else {
    bubblegap.className = "bubblegap-even";
  for (var j=0; j<x_bubbles; j++){
    var bubble = document.createElement("div");
    bubble.className = "bubble";
    var bubbleOverlay = document.createElement("div");
    bubbleOverlay.className = "bubble-overlay";
    bubble.setAttribute('onclick',function(){popBubble()} );
    if (j != (x_bubbles-1)){
       var bubblespace = document.createElement("div");
       bubblespace.className = "bubblespace";

Now the application is resized as a function of the screen without using the scale and translate functions and it can be successfully loaded and run on Android 2.x, Android 4.x, iOS devices and in desktop browsers.

Tested Devices

  • HTC One V (Android 4.0.3)
  • Sony Xperia Go Smartphone (Android 2.3.7) 
  • Samsung Galaxy Tab 2 (7.0) (Android 4.0.3)
  • Apple iPad 2 (iOS 5.1.1)
  • Desktop Browsers: Google Chrome 21.0.1180.89, Safari 4.0.5
Einzelheiten zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.