Monday, April 30, 2012

PhoneGap Android SplashScreen Just Got Better

One PhoneGap 1.7.0 is released in the next day or so doing a splash screen on PhoneGap Android is going to get a lot better. First off the long standing issue of using 9-patch images has been fixed. Really and truly it has this time. I've tested the fix on three different screen sizes.

Secondly, when you setup a splash screen you do the following:



super.setIntegerProperty("splashscreen", R.drawable.splash);
super.loadUrl("file:///android_asset/www/index.html", 10000);
This would show your splash screen 10 seconds then your index.html page would be loaded. Notice I said then. Yup, that's right showing the splash screen is a blocking call. While the splash screen is being displayed your .html/.js/.css is not being loaded in the background. Well, that is all changing so that your splash screen is shown on one thread while your application loads underneath the splash screen in another thread. The best thing is you don't need to make any changes to your code. Just keep calling the splash screen like you normally would.

But wait, I'm anticipating your next question "What if I want the splash screen to go away once my application is loaded before the timeout value is reached?" Okay, I've got good news it's coming. The official way to do this on iOS and Android once the 1.8.0 release is out will be to call:
navigator.splashscreen.hide();
but that call isn't ready yet. However, if you want to be on the bleeding edge you should be able to call:
cordova.exec(null, null, "SplashScreen", "hide", []);
but you are wait out on the edge there so don't blame me if it doesn't work. Then you'll be able to tell the splash screen to go away once you have "deviceready".
document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    console.log("We got device ready");
    cordova.exec(null, null, "SplashScreen", "hide", []);
    // Soon to be
    // navigator.splashscreen.hide();
}
That's all for now.

Friday, April 20, 2012

Migrating your PhoneGap Plugins to Version 1.5+

One of the pain points when we had to rename PhoneGap to Apache Cordova was that it kinda/sorta broke the plugins. Wherever possible we tried to put a shim in to keep plugins from breaking but some restructuring of the code made it impossible for this transition to be totally seamless.

So let's take a look at a new plugin I just created that gets you the IMEI of your Android phone. First here is the 1.4.1 version of the code:

and now the 1.5+ version:
As you can see the code is very different. Really the only changes are that PhoneGap has been replaced with cordova. There is actually a shim in place so that you can still use the PhoneGap object but that is going away for the 2.0 release so we might as well get on that train now. As well the addConstructor/addPlugin methods won't really be needed come 2.0 but lets leave them in for now.

Alright, so the JavaScript code wasn't much different so let's dive into the Java code now. First the 1.4.1 version:

and now the 1.5+ version: again not too many changes. Simply changing the imports from:
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
to:
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
This shouldn't be necessary for your plugin as I added code in the cordova.jar file so that every class in the org.apache.cordova.api package has a sub-class in com.phonegap.api. Once again this will be going away in the 2.0 release so we should go ahead and make the change now. Easy right?

Well kinda, but I'm being a bit disingenuous as my example does not address a key change between versions 1.4.1 and 1.5.0. In PhoneGap 1.4.1 the member variable this.ctx was of type PhonegapActivity. If you walked up PhonegapActivity's inheritance chain you'd see that android.content.Context is one of it's super classes. This was particularly useful in a number of Plugins.

In Cordova 1.5+ the member variable this.ctx is a CordavaInterface. So plugins that are passing this.ctx into methods that are expecting a Context will complain. The fix for this in your Java code is to replace:
this.ctx
with:
this.ctx.getContext()
or
this.ctx.getIntent()
with:
((DroidGap)this.ctx).getIntent()
wherever required. These changes were predicated by refactoring of the code in order to enable Cordova to be an embeddable component. That is, at some point in the future you will be able to create an Android application that can embed the Cordova component. This will allow you to mix native and hybrid development more easily.

Update 2012/04/23: Paul Beusterien pointed out that I forgot to mention a couple of steps to get the IMEI plugin working. First add the following line to res/xml/plugins.xml:
<plugin name="imei" value="com.simonmacdonald.imei.IMEIPlugin"/>
and make sure you have the proper permissions setup in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Wednesday, April 18, 2012

FileTransfer.download on PhoneGap/Apache Cordova 1.5.0

Sorry for being gone so long, vacation put me off my posting stride but hopefully this week will get things back on track.

Today I'd like to talk about using the FileTransfer.download() command with PhoneGap. In PhoneGap 1.5.0 we introduced common JavaScript. This is a sub project which has each platform that PhoneGap supports pulling it's JS from a common source. One of the changes introduced because of this is that all FileEntry.fullPath's would start with the "file://" protocol.

Unfortunately the native FileTransfer.download() code was not updated to take care of the new input. I've raised CB-539: FileTransfer.download fails when target starts with "file://" to track this issue. I've already got a fix for this checked into the source repository and it'll be in the 1.7.0 release of PhoneGap.

In the meantime you'll need to strip the "file://' from the target path you pass into FileTransfer.download().  Something like this:
var localPath = fileEntry.fullPath;
if (device.platform === "Android" &&
  localPath.indexOf("file://") === 0) {
    localPath = localPath.substring(7);
}
Here is a full example and don't forget to whitelist "http://i3.kym-cdn.com":

Monday, April 2, 2012

Updates to my PhoneGap Plugins

If you've updated to PhoneGap 1.5.0 which is part of our move to the Apache Cordova name and the next step in becoming an official Apache project you've probably noticed a number of plugins have broken. The biggest problem is that a lot of Plugins used this.ctx as an Android Context. Unfortunately due to some internal code changes this.ctx is no longer a Context. Now you have to call this.ctx.getContext(). So I spent sometime updating the ChildBrowser, FtpClient, TTS and VideoPlayer plugins so they would work smoothly with PhoneGap/Cordova 1.5.0.

Also, thanks to some code submitted by Stephanie Sherriff (ssherriff on GitHub) the VideoPlayer plugin can now play files from your Android assets folder. The syntax is pretty simple as well.
window.plugins.videoPlayer.play("file:///android_asset/www/path/to/my/video.mp4");

Friday, February 24, 2012

Books I've Read This Week


The Information Diet by Clay Johnson is exactly the type of book I needed to read after my new year's resolutions. I knew that I needed to curb the amount of information that I was consuming on a daily basis but I needed some strategies in order to accomplish it. Reading The Information Diet put me in touch with the tools and techniques I needed to make this change. I've been using RescueTime to track how my day is spent and make changes. After a couple of weeks of using the tool I realize that I'm less productive in the mornings than I am in the afternoon. This is not a surprise to me as I am Night Owl and not a Morning Lark. However, I'm making looking to make a change in my behaviour so I start everyday as a producer and not a consumer. This means the last thing I do before leaving work each day will be to setup a task I can tackle the following morning before I read my email or answer any StackOverflow questions.

Besides making me more productive the book was a very enjoyable read. Particularly the section dealing with how news agencies prey on our confirmation bias in order to get us to keep consuming their brand of news.

The book is also very digestible as it uses compares the consumption of information to our consumption of food. Johnson is able to make comparables between the consumption of bad food and it's effects on our bodies and the consumption of bad information and it's effects on our minds.

Here's the books trailer:

See you next Friday.

Wednesday, February 22, 2012

Rick Mercer's Rant on Online Privacy



Thank goodness someone is looking out for Canadians online privacy. Mind you it is a comedian. It would be nice if the opposition was doing more to shut down bill C-30. You can sign the Liberals petition along with 30,000 other Canadians.

Friday, February 17, 2012

Books I've Read This Week


The Nerdist Way by Chris Hardwick is not really a self help book it is more like an advice book. In it Chris details ways in which you can use the ability to obsess over things that most nerds, like myself, have and use it to enhance you life. A lot of it comes down to getting out of your own way and allowing yourself to succeed. That is stop thinking about it and just do it!
Watch is the second book in Robert J Sawyer's WWW Trilogy. I've previously reviewed the first book, Wake, which I loved. It continues the story of Caitlin Decter and the emerging artificial intelligence Webmind. Since this is the second book in the series I don't want to get to specific but I will say that Mr. Sawyer continues to write a very believable 16 year old girl character and I really appreciate how he deftly handles the moral/ethical/legal implications of the emerging AI. One of the things I've always admired about Sawyer's writing is that it is almost always uplifting. Yes, bad things do happen but there is always a sense of hope for the future unlike a number of dystopian sci-fi epics.

See you next Friday.