Monday, April 19, 2010

Telus iPhone Visual Voicemail

I was pleased to see that Telus announced and rolled out Visual Voicemail, as was implied in the Carrier Update file I received and analyzed.


I guess that means I may well look into the next carrier update file I receive, since the first one gave me a clue to an upcoming rollout.

Friday, April 2, 2010

OS X 10.6.3 and GWT 1.x

Safari 4.0.4, when it came out, had an issue with respect to GWT development, causing the GWT hosted mode browser to crash on load. As a result, I didn't take the Safari 4.0.4 update. When Safari 4.0.5 came out, reports indicated that it wasn't any better, despite the fact that some of the interim builds of WebKit had been used successfully, so I didn't take that update either.


Unfortunately, I did take OS X 10.6.3, which apparently came down with Safari 4.0.4 and broke my GWT development environment. I tried upgrading to Safari 4.0.5, but had no success. Eventually, I settled on the workaround that others were using with the WebKit nightly build (comment #22 on that issue) which seems to have solved my problems.

I did also briefly look into upgrading my current project to GWT 2.0.3; seems like it works pretty well, but we're coming up on a release point and it's an awkward time to do a framework upgrade. I'm hoping that by broadcasting this, some of you will avoid this same path.

Wednesday, March 17, 2010

Telus iPhone Carrier Update

This morning, iTunes warned me that there was a carrier update available for my iPhone. The 'more info' button opened a link that explained the process, but didn't offer any details about what the update contained, other than updates with regard to my settings for my carrier, Telus.


In the spirit of interested inquiry, I thought I'd follow in the footsteps of others, and take a peek inside the update file. I started by copying the carrier file to a temporary folder and extracting the contents:

$ mkdir ~/telus
$ cp ~/Library/iTunes/iPhone\ Carrier\ Support/Telus_ca.ipcc ~/telus/telus.zip$ cd ~/telus$ unzip telus.zip
Archive: telus.zip
creating: Payload/
creating: Payload/Telus_ca.bundle/
inflating: Payload/Telus_ca.bundle/carrier.plist
inflating: Payload/Telus_ca.bundle/Default_CARRIER_TELUS.png
inflating: Payload/Telus_ca.bundle/FSO_CARRIER_TELUS.png
inflating: Payload/Telus_ca.bundle/Info.plist
inflating: Payload/Telus_ca.bundle/version.plist

After that, I took a quick peek at the carrier.plist, but it was in binary format, so I had to convert the .plist files to XML:


$ plutil -convert xml1 *.plist

That let me take a look at the .plist files. The info.plist and version.plist files were very dull, looks like metadata about the bundle. The carrier.plist file was slightly more interesting:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BookmarkURLs</key>
<array>
<dict>
<key>BookmarkName</key>
<string>TELUS Web</string>
<key>BookmarkURL</key>
<string>http://m.telusmobility.com/homepage</string>
</dict>
</array>
<key>CarrierBookmarks</key>
<array>
<dict>
<key>Title</key>
<string>Web TELUS</string>
<key>URL</key>
<string>http://m.telusmobility.com/homepage</string>
</dict>
</array>
<key>CarrierName</key>
<string>TELUS</string>
<key>IntlDataRoamingSwitch</key>
<true/>
<key>MMS</key>
<dict>
<key>GroupModeEnabled</key>
<false/>
<key>MMSC</key>
<string>http://aliasredirect.net/proxy/mmsc</string>
<key>MaxRecipients</key>
<integer>20</integer>
<key>Proxy</key>
<string>74.49.0.18:80</string>
</dict>
<key>MaxBluetoothModemConnections</key>
<integer>1</integer>
<key>MyAccountURL</key>
<string>http://m.telusmobility.com/homepage</string>
<key>MyAccountURLTitle</key>
<string>TELUS Web</string>
<key>Services</key>
<array>
<dict>
<key>ServiceCode</key>
<string>#411</string>
<key>ServiceName</key>
<string>Directory Assistance</string>
</dict>
<dict>
<key>ServiceCode</key>
<string>#411</string>
<key>ServiceName</key>
<string>Assistance-annuaire</string>
</dict>
<dict>
<key>ServiceCode</key>
<string>#8294</string>
<key>ServiceName</key>
<string>TAXI</string>
</dict>
<dict>
<key>ServiceCode</key>
<string>#2886</string>
<key>ServiceName</key>
<string>Roadside Assistance</string>
</dict>
<dict>
<key>ServiceCode</key>
<string>#2886</string>
<key>ServiceName</key>
<string>Assistance Routière</string>
</dict>
</array>
<key>ShowCallForwarded</key>
<false/>
<key>ShowCallForwarding</key>
<false/>
<key>ShowDialAssist</key>
<false/>
<key>ShowTTY</key>
<false/>
<key>StatusBarImages</key>
<array>
<dict>
<key>AllowPrefixMatching</key>
<false/>
<key>CarrierName</key>
<string>TELUS</string>
<key>DefaultImage</key>
<string>Default_CARRIER_TELUS.png</string>
<key>FullScreenOpaqueImage</key>
<string>FSO_CARRIER_TELUS.png</string>
</dict>
<dict>
<key>AllowPrefixMatching</key>
<false/>
<key>CarrierName</key>
<string>TELUS UMTS</string>
<key>DefaultImage</key>
<string>Default_CARRIER_TELUS.png</string>
<key>FullScreenOpaqueImage</key>
<string>FSO_CARRIER_TELUS.png</string>
</dict>
</array>
<key>StockSymboli</key>
<array>
<dict>
<key>symbol</key>
<string>T.TO</string>
</dict>
<dict>
<key>symbol</key>
<string>TU</string>
</dict>
</array>
<key>SupportedSIMs</key>
<array>
<string>302220</string>
</array>
<key>SupportsNITZ</key>
<true/>
<key>SupportsUserBusyCauseCode</key>
<true/>
<key>VVMIgnoresIntlDataRoaming</key>
<false/>
<key>VisualVoicemailServiceName</key>
<string>IMAP</string>
<key>apns</key>
<array>
<dict>
<key>apn</key>
<string>sp.telus.com</string>
<key>password</key>
<string></string>
<key>signature</key>
<data>
...
</data>
<key>type-mask</key>
<integer>7</integer>
<key>username</key>
<string></string>
</dict>
<dict>
<key>apn</key>
<string>isp.telus.com</string>
<key>password</key>
<string></string>
<key>signature</key>
<data>
...
</data>
<key>type-mask</key>
<integer>48</integer>
<key>username</key>
<string></string>
</dict>
<dict>
<key>apn</key>
<string>sp.telus.com</string>
<key>password</key>
<string></string>
<key>signature</key>
<data>
...
</data>
<key>type-mask</key>
<integer>6</integer>
<key>username</key>
<string></string>
</dict>
</array>
<key>com.apple.voicemail.imap</key>
<dict>
<key>BeaconAddress</key>
<string>474663</string>
<key>ClientManagesTrash</key>
<false/>
<key>GreetingNotification</key>
<true/>
<key>MaxGreetingDuration</key>
<integer>60</integer>
<key>MaxPINLength</key>
<integer>10</integer>
<key>MinPINLength</key>
<integer>4</integer>
<key>UsesMWI</key>
<true/>
<key>UsesSSL</key>
<false/>
</dict>
<key>voicemail_context</key>
<integer>0</integer>
</dict>
</plist>

I won't claim to understand the meaning of all those settings, but some of them seem to point to Telus supporting visual voicemail, which would be interesting. And finally, the .PNG files, once decoded from iPhone PNG format, were themselves pretty boring. Very small transparent images of the word "TELUS" in all caps; these are referenced in the .plist above as Status Bar Images.

Monday, January 25, 2010

Composite Event Handler Registrations in GWT

In my previous entry, I wrote up a class for displaying Input Prompts in GWT. As I started to fold that code into my project, I realized that I didn't expose the handler registrations, which would make it impossible to remove the event handlers if and when the text fields for which input prompts were displayed were created and removed during the lifecycle of the application.

Because the Input Prompt registers handlers for both Blur and Focus, there are two registrations. It's not easy to return two values from a single method, and frankly, I don't think a class using InputPrompt should have to know or care what events it's employing in great detail. As a result, I've created a composite event handler registration to return:


package com.codiform.gwt.event;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.shared.HandlerRegistration;

public class CompositeHandlerRegistration implements HandlerRegistration {

private List registrations;

public CompositeHandlerRegistration() {
registrations = new ArrayList();
}

void add( HandlerRegistration registration ) {
if( registration instanceof CompositeHandlerRegistration ) {
CompositeHandlerRegistration composite = (CompositeHandlerRegistration) registration;
registrations.addAll( composite.getRegistrations() );
composite.clear();
} else {
registrations.add( registration );
}
}

private List getRegistrations() {
return registrations;
}

public void removeHandler() {
if ( registrations.size() > 0 ) {
for ( HandlerRegistration item : registrations ) {
item.removeHandler();
}
clear();
} else {
throw new IllegalStateException( "Composite handler registration is currently empty, and cannot remove handlers." );
}
}

private void clear() {
registrations.clear();
}

}


If a composite handler registration is passed to another composite handler registration, I flatten them; this might be unnecessary. In the spirit of YAGNI, I won't be at all unhappy if you decide you don't need that capability. I also decided I preferred to clear my local references to any inner handler registrations as soon as they've been removed, rather than hanging on to them indefinitely.

All in all, this is pretty simple GWT code, but seemed worth following up on the previous entry to talk about the need for handler registrations.