Uw betrouwbare partner voor (mobiele) web applicaties
TwitterEmailRSS

Phonegap Android splash screen: using 9patch images

When working on your new killer app, most of the time you are focussing on its functionality. Making wireframes and implementing that cool feature that makes the app different from all other apps. And eventually, when the implementation is almost finished you start working on the other stuff that is needed for your app, like the App store images and texts and the splash screens. At least, that is what it comes down too for us most of the times 🙂

However, configuring and implementing some nice splash screens for your Phonegap app appeared to be quite a challenge. Especially the Phonegap Android splash screen configuration is not that easy. How did we manage to get the Android splash screens in our app without being stretched? Turned out we had to use 9patch images. This blog describes how to create and configure 9patch splash screens for your Phonegap application.

Creating your 9patch image

The Android SDK comes with a tool called draw9patch, which is located in the tools directory of the Android SDK. This tool can be used to create your 9patch image. Follow the steps below to create your 9patch splash screen image.

  1. Open the draw9patch tool
  2. Open the PNG file you want to use as source for your splash screen
  3. Add the black dots on the outer side of the image for the part of the image you want to be stretched (see the example below). It is important that the right and bottom side of the image are completely filled with black (otherwise some strange stretched results might be visible).
  4. Verify the results in the preview pane of the tool (on the right side of your screen).

Phonegap Android splash screen

Configure Phonegap Android splash screen

What configuration do you need to add to your Phonegap app to use the 9patch splash screen you just created?

  1. Create splash.xml
  2. Configure the splash screen in your DroidGap activity
  3. Copy the splash screens in your drawable directories

splash.xml

A file named splash.xml should be created in your res/drawable folder. An example is listed below. You need to refer to the 9patch splash screen you’ve made earlier (use the filename without the extension).

<nine-patch 
xmlns:android="http://schemas.android.com/apk/res/android"
android:scr="@drawable/<splash_screen_name_without_extension>"
android:dither="false"/>

Configure the splash screen in your DroidGap extension

Next, you need to refer to the splash screen in your App’s Main Activity, which extends the Phonegap DroidGap class. Note that R.drawable.splash refers to splash.xml. Renaming splash.xml means changing this lines accordingly.

super.setIntegerPoperty("splashscreen", R.drawable.splash);

Copy the splash screens  in your drawable directory

Since we have created only one 9patch splash screen, first I though it was enough to simply put in the res/drawable folder of your app. However, it appeared that Android takes this to be a mdpi splash screen and it will still rescale and resize it to ie. hdpi density before the 9patch streching becomes active. To prevent this, copy the 9patch splash screen to all density subfolders in your res folder (drawable-mpdi, drawable-hpdi, etc.). Of course, it possible to create a different 9patch per density too, since you have more space available for higher densities.

And what about Phonegap Build?

The instructions above describe how to create and configure your Phonegap Android splash screen using a 9patch image. Can we use 9patch splash screens when using Phonegap Build?
Nope, you can’t 🙁 But there is hope… They have an open issue on their issue list so 9patch support will probably be added in the future.

Phonegap barcode scanner implementation

This article describes how to implement the Phonegap barcode scanner plugin in your mobile application. Most of the time we use the Phonegap Build environment provided by Adobe to build our mobile Phonegap applications for different platforms, mostly being iOS and Android. The Phonegap Build environment makes it very easy to build your applications for the platforms. It is just a matter of uploading your Javascript, CSS and HTML to the build server and Phonegap Build compiles and wraps your code in a platform specific build.

Phonegap Build

So… this all sounds very nice. Are there no drawbacks to Phonegap Build? Of course there are. For example, it is not possible yet to use your own Phonegap plugins. PhoneGap Build offers a limited set of plugins that can be used. The plugins that are available are listed here. One of the plugins that has recently been added is the BarcodeScanner plugin, which we have used in our mobile apps quite extensively.

Phonegap Barcode Scanner

The Phonegap barcode scanner plugin provides functionality to scan a barcode using the camera of your mobile phone. We have used the scanner to implement our KaartSaldo app, which can be used to determine how much money you have left on an electronic gift card that you’ve received (check out www.giveacard.nl for some nice gift cards). These gift cards have a barcode on the back which can be scanned.

So, how to implement the barcode scanner plugin in your application? The first step is to include the BarcodeScanner plugin in your config.xml. This file is used by Phonegap Build to determine what to include in your native wrapper app and how to configure it (i.e. what is the name of the app, what are the splash screens, etc.).

<gap:plugin name="BarcodeScanner"/>

The second step is to include the javascript in your HTML file.

<script src="barcodescanner.js"></script>

After including the javascript you are ready to implement your nice scanning feature. This can be done fairly easy. See the code snippet below for the scan function we have implemented.

function scan(successFunction) {
    var scanner = cordova.require("cordova/plugin/BarcodeScanner");
    scanner.scan(function (result) {
          if (!result.cancelled) {
            // Successfully scanned a bar code
            if (result.format == "CODE_128") {
              loadCardData(result.text, successFunction);
            } else {
              $('#typeInPopup #hint').html("Sorry, invalid format");
              $('#typeInPopup').popup('open', { transition: 'pop'});
            }
          }
        }, function (error) {
          alert("Scanning failed: " + error);
        }
    );
}

In the function scan you can see how to call the BarcodeScanner plugin from your custom javascript function. You provide a success callback function to handle a successful scan and an error callback function to handle errors while scanning. This is all you have to do. Check the documentation of the plugin here for the different barcode formats that are supported.

PhoneGap pull to refresh implementation

We all know the very nice pull to refresh functionality that was introduced in the Twitter app for iOS. Though patented by Twitter, it has been implemented in many apps since. I was working on a PhoneGap app with a page containing a list of news items and was wondering how difficult it would be to implement the pull to refresh functionality on that page. This blog describes how to make your PhoneGap pull to refresh implementation.

PhoneGap pull to refresh

Google led me to the iScrollView JQuery Mobile plugin to use the iScroll scroller. Using this plugin it was fairly easy to implement pull to refresh. A few steps had to be taken. First, include the plugin stylesheets and javascript files in your html file.

<link rel="stylesheet" href="css/jquery.mobile.iscrollview.css" type="text/css"/>
<link rel="stylesheet" href="css/jquery.mobile.iscrollview-pull.css" type="text/css"/>
<script src="js/lib/iscroll.js"></script>
<script src="js/lib/jquery.mobile.iscrollview.js"></script>

Next, add the attribute data-iscroll to the container you want to add the functionality to. In my case, this was the content container of the page. See the first line in the code snippet below.

<div id="scroller" data-role="content" data-iscroll="">
 <div class="iscroll-pulldown">
   <span class="iscroll-pull-icon"></span>
   <span class="iscroll-pull-label"
         data-iscroll-loading-text="News is being refreshed"
         data-iscroll-pulled-text="Release to refresh the news">
     Refresh the news
   </span>
 </div>
 <div id="newsList"></div>
</div>

The <div> with class iscroll-pulldown contains the definition of the pulldown content that will be displayed when the user pulls down the container. Different data tags are available for the different states the pull down dialog can be in. data-iscroll-loading-text for the text to be displayed when the update action is executed and data-iscroll-pulled-text for the text to be displayed when the user has pulled down the container.

So, how do we implement the code to actually update the news items? We need some Javascript for that ofcourse! On the pageinit event of the page we need to bind javascript functions to the different events that have been defined by the plugin. See the code below how the javascript function onPullDown is defined for the iscroll-onpulldown event.

$('#newsPage').live("pageinit", function(event) {
  $(".iscroll-wrapper").bind( {
    iscroll_onpulldown : onPullDown
  });
});
function onPullDown(event, data) {
  //do your stuff here...
}

This is all that is needed to implement the pull to refresh functionality in your JQuery Mobile PhoneGap application. Enjoy!

Implementing JQuery Mobile buttons without unexpected side effects

Recently we started the implementation of a new mobile application. We are using the Phonegap / Apache Cordova framework to have a single code base for multiple target platforms. The code base exists of HTML, CSS and Javascript. We use JQuery Mobile to implement the HTML pages.

JQuery Mobile offers different templates, the single page template and the multi page template. We are using the multi page template, which of course means that there are multiple pages in our application. These pages are defined in a single HTML file using the following JQuery Mobile code:

<div id="pageOne" data-role="page">
  Page code here
</div>
<div id="pageTwo" data-role="page">
  Page code here
</div>

Adding behaviour to your buttons

After creating the pages, we added some buttons to these pages. To add behavior to these buttons, we used the JQuery “pagebeforeshow” event of the page.

$('#pageOne').live('pagebeforeshow', function(e, data) {
  $('#myButton').bind('click', function() {
    $.mobile.changePage("#pageTwo", {transition: 'slideup'});
  });
});

After creating several pages and buttons we were ready to run our application to see if the navigation between the pages worked correctly. At first, we were very happy because all buttons seemed to work correctly. However, clicking around for a bit resulted in some very strange unexpected behavior. It turned out that each time the page was shown, the event handler was added to the page. Multiple event handlers to buttons result in ‘clickthroughs’, which basically means that page navigation is messed up.

How to fix this?

Finding the root cause proved to be more difficult than fixing the issue. Just unbind the click behavior of buttons when hiding the page, see the code snippet below. This will prevent multiple event handlers being added to your buttons.

$('#personPage').live('pagebeforehide', function(e, data) {
  $('#previousPerson').unbind('click');
  $('#nextPerson').unbind('click');
});

Control soft keyboard on Android 2.2 device in PhoneGap / Cordova application

Currently we are developing an application using the PhoneGap / Apache Cordova framework. During the project it became clear that it is difficult to control the behavior of the soft keyboard on Android devices. On iOS the keyboard works exactly as expected but on an Android 2.2 device (HTC Desire) we face some unexpected behavior.

The problem

We have a screen with a form with several input fields on it. After entering the value in the first input field, we want to step to the next input field using the soft keyboard enter button (Note that the Android 2.2 keyboard does not have a previous and next button) and the keyboard should keep popped up to enter the value in the second input field. This turned out to be difficult to implement. See below our solution.

The first implementation

In PhoneGap / Apache Cordova we can use Javascript to handle the enter event and set the focus on the next input field (see code below).

  x$('#inputfield1').on('keyup', function(e) {
    var theEvent = e || window.event;
    var keyPressed = theEvent.keyCode || theEvent.which;
    if (keyPressed == 13) {
    	// On enter, go to next input field
        document.getElementById('inputfield2').focus();
    }
	return true;
  });

So far, so good. The code seems clean and simple and it works! On our iPhone 4s the focus is set on the next input field and the keyboard is available to enter. On our Samsung Galaxy s3 we cannot use the enter button on the keyboard, but we have a previous and next button to navigate between the input fields, so a workaround is available. On our HTC Desire Android 2.2 device however, we don’t have a previous and next button available on the soft keyboard. The enter button sets the focus on the next input field, but the soft keyboard disappears. Now that is not helping users to enter their input quickly!

Phonegap / Cordova plugin

A quick google search on “android soft keyboard phonegap show hide problem” gave us 111.000 hits. One of the first hits led us to the PhoneGap SoftKeyBoard plugin. This is a Java PhoneGap plugin for Android devices to show and hide the soft keyboard. The implementation of the method showKeyboard looks like this:

public void showKeyBoard() {
  InputMethodManager mgr =
    (InputMethodManager) this.ctx.getSystemService(
    Context.INPUT_METHOD_SERVICE);

  mgr.showSoftInput(webView,
    InputMethodManager.SHOW_IMPLICIT);

  ((InputMethodManager) this.ctx.getSystemService(
    Context.INPUT_METHOD_SERVICE))
    .showSoftInput(webView, 0);
}

Unfortunately, using the plugin did not solve our problem. It lead us to another idea however. We changed the implementation of the method showKeyBoard to:

public void showKeyBoard() {
  InputMethodManager mgr = (InputMethodManager)
    this.ctx.getSystemService(
    Context.INPUT_METHOD_SERVICE);

  if (!isKeyBoardShowing()) {
    mgr.toggleSoftInput(0, 0);
  }
}

Using this implementation we are able to show and hide the soft keyboard using the javascript below.

x$('#inputfield1').on('keyup', function(e) {
  var theEvent = e || window.event;
  var keyPressed = theEvent.keyCode || theEvent.which;
  if (keyPressed == 13) {
    // On enter, go to next input field
    document.getElementById('inputfield2').focus();
    showSoftKeyBoard();
  }
  return true;
});

function showSoftKeyBoard() {
  if (isAndroid()) {
    window.plugins.SoftKeyBoard.show(function () {
      //success
      console.log("Showing keyboard succeeded");
    },function () {
       //fail
       console.log("Showing keyboard failed");
    });
  }
}

So, slightly adjusting the java code of the Android SoftKeyBoard plugin solved the problem for our HTC Desire Android 2.2 device.

Using PhoneGap Build?

Unfortunately, it’s not currently possible to add your custom Java code to apps built with PhoneGap Build. But if you do use that great Adobe cloudservice, check out this nice new app we created: Buildmeister, a mobile app for managing your PhoneGap Build apps.

Download Buildmeister for these platforms:

Android app on Google Play

Buildmeister - X-Services

Keeping your libraries up to date with libwat.ch

Every software developer recognizes this: You develop your application using a lot of different frameworks and libraries (JQuery, HibernateRichFaces, etc) and every now and then you have to check the website of all these frameworks and libraries to see if a new version has become available. This takes a lot of valuable time that could also be spent developing that cool new feature your client has asked for.

Here at X-Services we experienced the same issue, which made us decide to implement a new service: libwat.ch.

Libwat.ch

Libwat.ch is a (mobile) web application that offers a simple service, it notifies you of updates of your favorite frameworks and libraries. There are two ways you can be notified:

  1. Follow the @libwat_ch Twitter account. We will send a tweet when a new version of a library is available.
  2. Register at www.libwat.ch and toggle the libraries you want to be notified of when a new version is available. See the screenshot below.

Add your own libraries

Is your favorite coding library not listed on libwat.ch? Don’t worry, you can send your suggestions and we’ll add them to the list. Please give us some time to add them, as we need to implement the parsing algorithm to check if a new version has been released.

Curious? Check www.libwat.ch