Uw betrouwbare partner voor (mobiele) web applicaties

PhoneGap ActionSheet plugin

Cordova PhoneGap ActionSheet plugin for iOS and Android

Recently I was wondering how hard it could be to add a Cordova plugin for showing a native ActionSheet like Twitter on iOS does:

Twitter ActionSheet iOS

.. so I gave it a try

The idea is to show the user a list of options and have the plugin return the selected index back to the JavaScript callback.

iOS implementation

The iOS implementation is based on UIActionSheet. It’s the exact same thing Twitter uses (and loads of other app by Apple and third parties). It supports these things, all of the labels can be passed in by the plugins JavaScript API:

– A title, on top of the dialog.

– Multiple options, shown in blue.

– A ‘desctructive option’, shown in red. This does the same as the other buttons, but can be used to indicate to the user this action can not be undone.

– A cancel button.


Android implementation

Before I could ever get around to implementing an Android version,  Brill Pappin stepped up and created a great implementation of an ActionSheet for Android. It’s based on the AlertDialog.

There are two differences to keep in mind when using this plugin on Android:

– The cancel button is hidden by default, even when a label for the cancel button was passed in. This is common Android behavior as all devices have a dedicated backbutton which can be used to close the popup as well. If you want a cancel button (like the screenshots), there is an option in the API to tell the plugin to do so.

– The ‘destructive option’ (the red ones in the iOS screenshots) don’t have  a different color.


Cool, gimme!

Head over to the GitHub repo, star it, and follow the instructions to install it.

What about PhoneGap Build?

Check out the plugin page and search for the ActionSheet plugin (I would have provided a deeplink, but the URL changes with every update of the plugin). Android support was added in version 1.0.0 which has not yet been approved at the time of writing.

PhoneGap Toast plugin

PhoneGap Toast plugin for iOS, Android and WP8

It’s always a good idea to show your mobile app user feedback about his actions. I have used the alert function of the Notification plugin a lot, but never really liked its blocking in-your-face behavior. You even force the user to click a button to continue using your app 🙁

Native Android apps have  a lovely little gem called a Toast and that’s exactly what this plugin tries to bring to PhoneGap apps. Now I can finally show feedback like ‘Logout succeeded’ or ‘Account created’ without annoying the user with a blocking popup, or showing an HTML message which may or may not be inside the viewport (don’t you hate it when your error message is rendered offscreen?). If you want feedback messages like this, use the PhoneGap Toast plugin:

PhoneGap Toast plugin on iOS

PhoneGap Toast plugin in action on iOS

PhoneGap Toast plugin on Android

PhoneGap Toast plugin in action on Android

Display text inside a native popup

Showing a Toast using some sensible default values would have been sufficient for most users, but I wanted to make it a bit more flexible than simply passing a message.. so let’s see what else we need.

Positioning the Toast

On Android, Toasts are often shown at the bottom of the app, but this may not satisfy all usecases. If you have a menubar at the bottom, it could block those buttons for a few seconds. Or what if the message is very important? Then you’d want to show it in the center of the screen. So I need the plugin to have a ‘position’ parameter.

Showing the Toast a bit longer

When you want to display more than a few words, you’ll want to show the Toast a bit longer. So I also need a ‘duration’ parameter. Since Android only supports ‘short’ (2 seconds) and ‘long’ (5 seconds), we have to settle with that. Note that you can use an arbitrary length on iOS, but I like uniform API’s.

Putting it all together: the Toast Javascript API

Now that the requirements are clear, it’s time to show the final API:

toast.show('Hello!', 'long', 'center')

Since there are only six options, I’ve added a few convenience methods:

toast.showShortBottom('I hit rock bottom..')
toast.showLongTop('I'm at the top of the app!')

What about PhoneGap Build?

Check out the plugin page and search for the Toast plugin (I would have provided a deeplink, but the URL changes with every update of the plugin).

PhoneGap share plugin for Facebook, Twitter and other social media

PhoneGap share plugin

Adding social media to your PhoneGap app is always a good idea – you can draw attention to your app by letting your users do the promotional work for you. All you need to do is adding share buttons for Twitter, Facebook and other social media to your app. BUT how does this work on PhoneGap.. and what about PhoneGap Build? Use this PhoneGap share plugin and you get stuff like this:

PhoneGap share plugin in action on iOS7

SocialSharing plugin in action on iOS 7

PhoneGap share plugin in action on Android

SocialSharing plugin in action on Android 4.4 (Kitkat)

Share text using the native sharing widget

Using this plugin, you can have your iOS or Android device open the native share widget, so the user can choose where to share the content to. For example, sharing a message ‘My message’ can be started by clicking a button:

<button onclick="window.plugins.socialsharing.share('My message')">share!</button>

Sharing a link

Sharing text is nice, but why not spice it up a little? Let’s add a link:

  share('My message',

Sharing an image

What about sharing an image? That’s possible as well. You can share links from the internet and from the local device. You can even share base64 encoded image which you just grabbed from the Camera!

  share('My message',
        'PhoneGap share plugin',
        'https://www.google.nl/images/srpr/logo4w.png', // check the repo for other usages

Sharing text, a subject, a link and an image together

Let’s combine all options and share like a boss! A subject can be used for the email client, but other apps may use it as well, but that’s up to the receiving app:

  share('My message',
        'PhoneGap share plugin',

Skipping the share dialogue

If you don’t want your user to choose where to share to, you can skip the share widget and directly share to Twitter, Facebook, or other apps:

  shareViaTwitter('My message');

  shareViaFacebook('Message via Facebook',
                   console.log('share ok'), // success callback
                   function(errormsg){alert(errormsg)}) // error callback

  shareVia('com.apple.social.sinaweibo' // for options, see the repo
           'Message via Weibo on iOS',
           console.log('share ok'), // success callback
           function(errormsg){alert(errormsg)}) // error callback

What about PhoneGap Build?

Check out the plugin page and search for the SocialSharing plugin (it’s one of the most used plugin thanks to you all!).

Certificate Pinning Plugin for PhoneGap to prevent Man in the Middle Attacks

A while ago my colleagues and I were working on a PhoneGap app which required a high level of security. Among other measures, we implemented certificate pinning to prevent Man in the Middle attacks. In this blog I’ll tell you what we’ve done and give you a link to a certificate pinning PhoneGap plugin I recently wrote.

Man in the Middle attackman-in-the-middle-attack

Ofcourse you have secured communication with an SSL certificate on the server. With a desktop browser, you will normally see the green certificate bar next to the URL. In a mobile app however, there is no such bar, so you won’t notice when it suddenly turns red because an attacker is impersonating the server with a self signed certificate. This may happen when f.i. you use the app via a compromised public WiFi hotspot. The attacker intercepts all traffic without the user noticing it.

Certificate pinning

A good way to make sure your app connects directly to your server, is by checking the fingerprint of the SSL certificate. In our app we implemented this purely in native code for iOS and Android and it works great; intercepting traffic via a proxy is no longer possible. (Note that we also encrypt the data itself, just in case this solution gets compromised.)

Native iOS and Android implementation

So what the code needs to do is fetch the certificate from the endpoint the app connects to and compare its fingerprint to a list of fingerprints your app allows to connect to. In Java, it looks a bit like this (simplified):

boolean isConnectionSecure(url, expectedFingerprint) {
  return expectedFingerprint.equals(getFingerprint(url));

String getFingerprint(String httpsURL) {
  HttpsURLConnection cnx = (HttpsURLConnection) new URL(httpsURL).openConnection();
  Certificate cert = cnx.getServerCertificate();
  MessageDigest md = MessageDigest.getInstance("SHA1");
  return getHex(md.digest());

PhoneGap plugin

I’ve wanted to enable fellow PhoneGap developers to use this feature via a plugin and finally took the time to create the plugin. With the plugin, developers can create a Javascript call like this one to verify the connection with the server:

var server = "https://build.phonegap.com";
var fingerprint = "8F A5 FC 33 20 2D 45 B4 EC 95 87 F0 50 F0 18 14 DF 98 50 64"; // valid until sep 2014


Once the successCallback is invoked, you can be pretty sure there is no Man in the Middle attack going on.

The SSLCertificateChecker plugin can be found here, on Github.

What about PhoneGap Build?

PhoneGap Build is fully supported by the plugin.

Oh, and if you are using PhoneGap Build, I highly recommend our Buildmeister app, which will make your development cycle a bit shorter:

Android app on Google Play

Buildmeister - X-Services

Sign an Android debug-APK for release in Play

“Video’s don’t play and the app is slow”

Game TV
That’s the feedback I got a day after publishing a new version of Game TV to the Google Play store. I thoroughly tested the debug version of the app (built with PhoneGap Build) and it worked fine. After installing the released version myself, I found that indeed the scrolling in the app was terribly sluggish and video’s only played in fullscreen (not as an embedded inline video).

UPDATE: PhoneGap Build has been fixed, so Build users can simply sign the release apk in the cloud.

What to do?

It turned out, I was not alone in this one: it’s a bug in PhoneGap Build where release APK files are incorrectly build (a.o. no hardware acceleration).

I could have waited for the bug to be resolved, but when writing this blog, the problem was already a month old. In the meanwhile I would’ve had a lot of complaints about Game TV. So I tried:

  • Reverting to the previous version of the app in Google Play. This wasn’t possible, because the newer version was already in use, so Play didn’t allow me to activate an older version.
  • Uploading a previously correctly built version. This didn’t work, because again, there was already a distributed version with a higher buildnumber.
  • Build the app offline, instead of using PhoneGap Build. Ofcourse this could have been done, but it would have been a significant effort and lots of testing, while loosing customers.

Then I wondered: “why can’t I release the debug version of the app?

Sign an Android debug-APK for release in Play

Well, it turns out you can. And that’s what solved my problem. Take these steps to use your debug apk and turn it into a release apk yourself (sorry, Mac example only):

  • Get your debug apk. In my case, I downloaded an unsigned build from PhoneGap Build (set the key-dropdown to ‘no key selected’).
  • Fire up a Terminal and cd to the folder where your apk lives. In this case: GameTV-debug.apk
  • Remove the META-INF dir which contains the debug certificate stuff:

    zip -d GameTV-debug.apk META-INF/\*

  • Now we need to sign it for release with our keystore. For PhoneGap Build users: this is what you uploaded when creating a release key for Android. You’ll need to replace alias_name with the correct value. Don’t know it? Running the first command will show all entries in your keystore, look for ‘Alias name’ in the output, then use that value in the second command:

    keytool -list -v -keystore /path/to/your.keystore

    jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore /path/to/your.keystore GameTV-debug.apk alias_name

  • This will prompt you for your keystore password and sign it with your release certificate.
  • Now it’s time to zipalign the apk and we’re done:

    zipalign -v 4 GameTV-debug.apk GameTV-zipaligned.apk

Upload your zipaligned apk to Google Play and sleep well 🙂

Promo: Using PhoneGap Build for your apps?

If you do, you may also want to use our nice new app: Buildmeister, a mobile app for easily managing your PhoneGap Build apps.
Android app on Google Play

Buildmeister - X-Services

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


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).


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 camera implementation

We are currently working on the implementation of a new App for a customer using the Phonegap framework to simplify development for multiple platforms. One of the requirements the customer came up with is the possiblity for a user of the App to upload photo’s that he made with the camera of his mobile device. Is this possible using the Phonegap framework? Of course it is, and this blog will show you how.

Photo upload using the Phonegap camera object

Several steps are needed to implement the photo upload functionality:

  1. Make sure your App has access to the mobile device’s camera functionality.
  2. Get you App to open the device’s native camera dialog.
  3. Get the photo from the native camera dialog.
  4. Upload the photo to your server.

1. Access to the device’s camera functionality

It is necessary to configure in your Apps’s Phonegap configuration that you’ll be using the Phonegap camera plugin.We are using Phonegap Build, which means that a single configuration file (config.xml) can be used for both Android and iOS.

The following lines have to be added to the config.xml:

<feature name="http://api.phonegap.com/1.0/camera"/>
<feature name="http://api.phonegap.com/1.0/file"/>

Note that the second line is needed because on Android you need to configure the user permission WRITE_EXTERNAL_STORAGE, see the Phonegap API documentation. This is needed to store the picture taken with the camera on the local file system.

When you are not using Phonegap Build, this needs to be done differently for Android and iOS.


<plugin name="Camera" value="org.apache.cordova.CameraLauncher" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


<plugin name="Camera" value="CDVCamera" />

2. Open the device’s native camera dialog

First, you want to tell the user that it is possible to upload a photo in the App. We added a camera icon to the page and added an onclick event to that icon. This onclick event opens a confirm dialog asking the user if he wants to 1) Make a photo and upload it or 2) Select a photo from the device’s gallery and upload it. After that, the Javascript method listed below is executed.

function onConfirm(buttonIndex) {
  if(buttonIndex == 1) { 
    // User wants to make a photo using the camera
    sourceType = Camera.PictureSourceType.CAMERA;
  } else if (buttonIndex == 2) {
    // User wants to select a photo from the gallery
    sourceType = Camera.PictureSourceType.PHOTOLIBRARY;
  } else {
    // cancelled

As you can see, this method does nothing more than setting the correct sourceType, which is a global var in the Javascript file and executing the method captureImage, which contains the magic. captureImage is listed below.

function captureImage() {
    { quality:60,
      allowEdit:true, // ignored by Android
      destinationType:Camera.DestinationType.DATA_URL, //base64

The captureImage method calls the Phonegap navigator.camera.getPicture method, which is the bridge to the native camera functionality of your mobile device. Some configuration settings are provided, i.e. the destinationType that tells Phonegap we want a base64 encoded image String, the encodingType to configure the image encoding type and the sourceType to tell the device that we want to make a new picture or select an existing image from the gallery. See the Phonegap API documentation for the complete list of configuration properties.

3. Get the photo from the native camera dialog

In order to obtain the photo from the native camera dialog, the onSuccess callback function listed in the captureImage method above needs to be implemented. Our implementation of the onSuccess method is listed below.

function onSuccess(imageData) {
  var theImage = "data:image/jpeg;base64,"+imageData;

  // immediately change the image in the view 
  clickedImage.src = theImage;

  // And now upload the photo to the server

4. Upload the photo to your server

To actually upload the photo to the server, we have extended the onSuccess callback function with an Ajax call to our server, which is shown in the listing below.

function onSuccess(imageData) {
  var theImage = "data:image/jpeg;base64,"+imageData;

  // immediately change the image in the view 
  clickedImage.src = theImage;

  $.mobile.loading('show'); // Show the spinner
       'personid': getUser().personID,
       'photo': imageData
    function(data) {
      if (data.success) {
        alert('Saving photo succeeded');
      } else {
        alert('Saving photo failed');
      $.mobile.loading('hide'); // Hide the spinner

On our server we store the base64 encoded JPEG file in our database for the user that uploaded it. The server side code is not included here.

Phonegap camera

As we described above, it is very easy to implement a photo upload mechanism in your Phonegap application using the Phonegap camera object. A few simple lines of Javascript code in your App is enough. Enjoy!

Using PhoneGap Build? You should.. if possible

Unless you need to add your own native code to your PhoneGap project, you can use the excellent PhoneGap Build service. If you do, you may also want to use our nice new app: Buildmeister, a mobile app for easily managing your PhoneGap Build apps.

Download Buildmeister for these platforms:

Android app on Google Play

Buildmeister - X-Services

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
 <div id="newsList"></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 id="pageTwo" data-role="page">
  Page code here

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) {