Wednesday, May 9, 2012

An Open Letter To Bell Mobility

Here is my unedited email I've sent to Bell Mobility today to complain about how they treat customers. Honestly, if any company out there is giving you good customer service you should praise them to the tops of the mountains. I really loved the fact that Samsung replaced my phone out of warranty last year but we'll see what happens this time around.

BEGIN
Hey,

In a nutshell this is my problem. I have a Samsung Galaxy S Captivate and it is stuck in a reboot loop. It boots up the Samsung screen and then you get the flash stylized S screen then reboots. This sequence continues to repeat itself until I pull the battery out of the back of the phone. I had this problem occur last October while I was attending a conference in San Francisco last year. When I got back to Ottawa and phoned Bell the representative told me they could do nothing as the phone was one week out of warranty. I don't want to even get into the debate of signing people up for 3 year contracts when the physical device won't last the three years. That is for another rant. Luckily Samsung was able to step up and provide me a replacement phone for which I'm eternally grateful for.

Now here we are 6 months later and the problem has re-occurred. I know this is a Samsung problem with their phone but where Bell has fallen down is in their response to helping their customer resolve the problem. I shouldn't have to go to Samsung to resolve this issue. I have a business relationship with Bell, I pay Bell $100 a month for my phone/data service not Samsung.

When the problem occurred last night I was in the Carlingwood Mall here in Ottawa. I went to the Bell store where two customers were being waited on and two more were in line in front of me. After waiting 10 minutes I decided to go get my haircut and come back to see if the line has lessened. Fast forward 15 minutes to which I returned to the Bell store and the same two customers were at the front counter and the same two customers were in front of me. I then waited another 15 minutes before I got to the front counter where a representative could help me.

Going in a knew the rep would not be able to fix my phone. My alternative solution was to purchase a micro-sim card and have my current number activated on that card. The cost would be $5 for the micro-sim, no biggie, but $35 to activate the SIM. Seriously!?! I'm not trying to game the system here, I just want to be able to use my service on another phone while I send my busted Samsung off to be fixed. Thanks for being so unhelpful.

I really feel that Bell missed an opportunity to make an existing customer happy and possibly if good customer service was provided convince me to switch my home phone/internet/TV to Bell.

Anyway that is my tale of woe.

Simon Mac Donald

END


To be fair here is the response from Bell.


BEGIN



Hello Simon and thanks for the email.

Every phone you purchase comes with a year manufacturer’s warranty and you have the option to purchase the phone insurance at $7 per month at the time of purchase.

If you wish to activate your old phone, please purchase the sim card at any Bell store, if you haven’t yet, and I will go ahead and apply a credit for $35 in order to waive the activation fee.

Please let us know when you would do this and the mobile number in question, as well as the type of equipment being activated.

Thank you and have  a great day.


Bell Twitter Support.



END


and finally my email to them.


BEGIN



Sure, I will take you up on your offer to waive the $35 activation fee. My cell phone number is xxx-xxx-xxxx, I will be activating an iPhone 4 and I probably won't be able to get to this until I get back from San Francisco late next week. In the mean time I'm using a different phone that doesn't require a micro-sim.

Just because I can't resist. Wouldn't this have been better if the customer agent at the Bell store have offered to waive the fee? To me that would have been better customer service and I wouldn't have taken to the internet to complain. Rather I'd have praised Bell for making the transition easier.

Simon Mac Donald


END

Tuesday, May 8, 2012

Speaking Engagements

Over the next few months I'll be making the rounds doing my Adding Speech Recognition to Your Android Applications presentation. If you've ever wanted to see someone attempt to entertain and inform a crowd and not worry if they are crashing and burning then you'll want to pop by and see me at:

  • AnDevCon III - San Francisco, May 16th
  • Ottawa Android - Ottawa, June 20th
  • OSCON - Portland, July 18th
  • PhoneGap 2.0 Day - Portland, July 20th (To Be Confirmed)
If you are going to be in or around those cities on those dates ping me on twitter and we'll see if we can arrange a meet up.

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.