Uw betrouwbare partner voor (mobiele) web applicaties
TwitterEmailRSS

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.

actionsheet-plugin-ios

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.

actionsheet-plugin-android

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',
        null,
        null,
        'http://www.x-services.nl')

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
        'http://www.x-services.nl')

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',
        'https://www.google.nl/images/srpr/logo4w.png',
        'http://www.x-services.nl')

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',
                   null,
                   null,
                   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',
           null,
           null,
           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");
  md.update(cert.getEncoded());
  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

window.plugins.sslCertificateChecker.check(
          successCallback,
          errorCallback,
          server,
          fingerprint);

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