Wednesday, July 28, 2010

Google Ion - Android 2.1 - cyanogenmod

Thanks to cyanogenmod, my Google Ion is happily running 2.1 basically following these directions

Happily means it runs smoother with less wait time for many things like viewing mail, opening a new chapter in a book, menus etc.

The steps were:

1) setup fastboot on my mac

2) obtain a suitable recovery image (to flash the cynogenmod ROM) I used clockwork-recovery-image

RA-sapphire-v1.7.0 is also said to work

3) downloaded and copied the cynogenmod ROM to my sdcard (and the google apps one too) after verifying their md5sum

4) Enter fastboot mode by holding down the back key while booting. Then, from a terminal on my mac, run:

./fastboot erase cache
./fastboot erase userdata
./fastboot flash recovery recovery-clockwork-2.5.0.1-sapphire.img

5) reboot and hold down the HOME key while rebooting to enter recovery mode

6) ran a backup from the recovery options

7) choose to load a zip from the sdcard (recovery option) and select the update-cm-5.0.8-DS-signed.zip

8) rebooted into 2.1 and set up my wifi (I've no data plan at the moment)

9) rebooted into recovery mode (HOME key) again and installed the google apps by choosing-a-zip-from-the-sdcard (recovery option)

gapps-ds-ERE36B-signed.zip

10) rebooted and set up my google account

Notes:
*I don't know the effect of installing the cynogenmod ROM and google apps at the same time.
*My radio image was HTC standard from 1.6
*My menus were all Japanese but I changed that to English (somehow). I'm in Tokyo so it makes sense I guess...

Thursday, July 22, 2010

GXT MVC Code Splitting on GAE (AppEngine)

This is an example of how I used GWT code splitting with GXT and ran it on Google AppEngine.

There seems to be some misunderstanding that controllers need be registered in advance which draws in all the code and disallows code splitting. This is not the case and controllers can easily be registered when and only when requested.

Code is available via GIT and the simple demo deployed on appengine.

This is just a simple rework for the GXT mail example.

First, we need the controllers we will use later.

TaskController taskController;
ContactController contactController;

Then, we add a listener to initialize them the first time they are used.

public void onModuleLoad() {
....

final Dispatcher dispatcher = Dispatcher.get();
dispatcher.addDispatcherListener(new DispatcherListener() {

@Override
public void beforeDispatch(final MvcEvent mvce) {

switch (CONTROLLERS.getControllerByEvent(mvce.getAppEvent().getType())) {


CONTROLLERS is just an enum set to return the controller for any event. Since there may be more than one event per controller, you could conceivably end up with something like the following which would work in a switch statement to do what you want.

public enum CONTROLLERS {
APP(AppEvents.Login),
APP2(AppEvents.Error),
APP3(AppEvents.Init),
//MAIL(AppEvents.Init),
MAIL2(AppEvents.NavMail),
MAIL3(AppEvents.ViewMailItem),
MAIL4(AppEvents.ViewMailItems),
MAIL5(AppEvents.ViewMailFolders),
TASK(AppEvents.NavTasks),
CONTACT(AppEvents.NavContacts);

In real apps I use GWT's History Mechanism
and another enum that lets me look up both the AppEvents and also the appropriate controller. But that enum-fu is best left out of this simple example.
Anyway, if the controller is null when called, we use GWT.runAsync to fetch it:

switch (CONTROLLERS.getControllerByEvent(mvce.getAppEvent().getType())) {
case CONTACT:

if (contactController == null) {
mvce.setCancelled(true);

GWT.runAsync(new RunAsyncCallback() {

@Override
public void onFailure(Throwable reason) {
//log
}

@Override
public void onSuccess() {
contactController = new ContactController();
dispatcher.addController(contactController);
GWT.log("fetched and added contactController");
Dispatcher.forwardEvent(mvce.getAppEvent().getType(), mvce.getAppEvent().getData());
}

});

}
break;

... etc. ect. for the other controllers

...For AppEngine, the trick was cancelling the dispatch and then re-calling it after the code was fetched. It worked on the development server in eclipse without recalling the event, but failed silently when deployed.


if (contactController == null) {
mvce.setCancelled(true);

...
Dispatcher.forwardEvent(mvce.getAppEvent().getType(), mvce.getAppEvent().getData());


I can see the deferred code being fetched in firebug and if I run the reports on a real project when compiling GWT, can see a difference in the initial size of the download. There are portions of my app that many users will never use, so it makes sense to do it this way.

Right now for an app .6 MB, .4 is initial and .2 is deferred (and not likely to be used by the majority of users). Keep in mind gxt2.x was designed before runAsync came out and from their mailing lists seems targeted to be redone for 3.0 (well, if "nothing can be done before v3" means targeted -- I don't really know how it'll change).

Followers