TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and Google Cloud Platform Instructor now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 224 other subscribers
  • Sleepless Nights…

    March 2023
    S M T W T F S
     1234
    567891011
    12131415161718
    19202122232425
    262728293031  
  • Blog Stats

    • 1,039,383 hits

Archive for the ‘Headsmack’ Category

Android demo tips: behind the scenes at Google I/O

Posted by David Chandler on May 20, 2013

Last week at Google I/O, Brad Abrams and I decided to go for the gold and give a talk on building a cloud backend for your Android app, complete with live coding on stage. For a more interesting example, we chose to build a sample app which relies on location services and Google Cloud Messaging. It all seemed like a good idea at the time. For the benefit of other Android presenters, I wanted to give a behind-the-scenes view of how we overcame some significant challenges to pull off the demos. Also, I will explain the anomalies we saw.

Device display. The easiest way to show an app is using an emulator, but Maps V2 API is part of Google Play Services, which doesn’t currently run on the Android emulator, so we needed physical devices. Droid@Screen works, but it updates slowly and requires the USB cable, which we needed for hardwired Ethernet. Some devices support HDMI out (Galaxy Nexus, N10) which can be used with a BlackMagic or similar HDMI capture box to show the device display on your Mac screen. Note that this requires a Mac with two Thunderbolt ports (hello Retina! BlackMagic in, Mac display adapter out). We could not use this because the phone’s HDMI connector is shared with the USB connector, which we needed for hardwired Ethernet. Fortunately, we had a Wolfvision projector camera available and a 4-port video switcher to show our Macs or the camera. For best results with a projector, set the phone display brightness to max.

The network. Gather 5000+ geeks in a massive concrete structure, give them all a new wifi device, and then try to get a working Internet connection… Despite Google’s stellar efforts, getting wireless Internet at Moscone Center remains very challenging. 3G / 4G / LTE is inhibited by the concrete and steel, and even 5GHz wifi suffered from RF interference or sheer demand. Thus, we knew in advance that we would need hardwired Internet. This was no problem for our laptops, but we also needed 2 phones for the demos to show continuous queries in action. Fortunately, Galaxy Nexus phones support wired connections using a USB OTG adapter paired with a USB to Ethernet adapter, and it just worked. So far so good.

Deferred launch. Because we were coding live in Eclipse, we deployed the code to the phones in real time via the USB cable. When you run an Android app in Eclipse, the default action is to install and run the app. But this  created a problem for the simple version of our demo app, which needed an Internet connection on launch to send a location update immediately. We had to disconnect the USB cable, walk the phone over to the camera, plug in the hardwired Ethernet, and only then launch the app via the home screen. Fortunately, Eclipse has a way to support this. In the project’s run configuration on the Android tab, simply select “Do nothing” for the launch action. This installs the app, but doesn’t launch it.

Live coding. Speaking of live coding, we have all seen those demos with lots of tedious cut and paste operations from a text file to the IDE. As a presenter, I want something visible in the IDE to prompt me for the fully manually steps as well as an easy way to paste in blocks of code. Eclipse snippets are just the thing. You can show them off to the side of your main editor window, then double-click on a snippet to paste it in. I used snippet titles without code to prompt me for the manual steps. Another challenge of live coding is that you might make a mistake at an early stage of the demo which ruins a later stage. In order to facilitate recovery, we created snapshots of working demo code at six different stages during our presentation. It would have been nice to preinstall these app versions on the devices; however, they all use the same package name and the Android installer doesn’t allow more than one at the same time. Hence the need for adb install and the deferred launch technique. Also we had to uninstall the prior version of the app on the device before each coding stage. Furthermore, Eclipse doesn’t let you create multiple projects with the same name. There is a workaround, but it kind of spoils the magic of our talk and I’ve already spilled enough secrets… let’s just say Eclipse workspaces and “Copy project” are a beautiful thing.

Location services. This is the one that snagged us in the first demo. It turns out that location services are not in fact magic, but require GPS (in Moscone?!) or wifi, which we turned off just before speaking to eliminate the possibility of conflict with the hardwired Ethernet. Fortunately, we were able to get a good enough wifi signal in a later demo to show location. On desktop devices, geolocation works with a hard-wired connection, so I’m not yet sure whether this is a bug or a feature on mobile… it is admittedly an uncommon use case.

The unanticipated. After recovering from the first demo glitch by turning on wifi, I demonstrated that location services worked, but it never sent the location to the server. It turns out the code was working as intended–I had already enabled authentication for my next segment, but the app from the previous segment which I revisited did not have auth turned on. Finally, the last demo showed two markers when it should have showed only one. The second marker turned out be a fellow Googler in the audience who had helped dogfood an early version of the demo app. So once again, the code worked as intended, just not as I intended at the moment. But… this is the stuff live demos are made of. I still prefer live demos with a few glitches to an hour full of slides 🙂

So now you know what Brad and I were busily doing while the other was talking and why talks of this complexity are pretty much impossible without two people and a lot of presentation gear. It was a teeny bit intimidating knowing that our session was part of the Google I/O live stream with thousands of viewers, but in the end, it came off (almost) without glitches and our gracious audience was wowed by the Mobile Backend Starter project. Mission accomplished!

See my next post for a complete list of resources on Mobile Backend Starter.

Advertisement

Posted in Android, Eclipse, Headsmack | 10 Comments »

ProgressDialog considered harmful

Posted by David Chandler on March 26, 2013

Roman Nurik recently wrote a G+ post favoring the use of inline ProgressBar over the pop-up ProgressDialog. Here are some additional reasons to consider.

To be sure, ProgressDialog is very convenient. It has a nice spinner and does its job very simply. You can create one as simply as

ProgressDialog pd = ProgressDialog.show(this, "Please wait", "working...");
...
pd.cancel();

The first problem is that by default, there is no way for the user to dismiss a ProgressDialog. A common scenario is to show the ProgressDialog before making a network request. But what happens if the user gives up before the request times out? The back button doesn’t work. The home button works as usual, but if you return to the app, the ProgressDialog is still there. To get rid of it, you have to force close the app.

This is easily remedied by setting an additional property:

ProgressDialog pd = ProgressDialog.show(this, "Please wait", "working...");
pd.setCancelable(true);
...
pd.cancel();

However, there is another problem which leads to a lot of confusion for Android or Java newbies. Consider this code which I have inadvertently written myself:

ProgressDialog pd = new ProgressDialog(this);
pd.setCancelable(true);
pd.show(this, "Please wait", "working...");

Like the first example, this will show a ProgressDialog which cannot be dismissed with the back button. Why? Because the show() method used here is a static method which returns a new ProgressDialog. The instance named pd is never shown. The compiler will show a warning that a static method is being invoked in a non-static way so you might get a clue that something is wrong; still, this is a really confusing API with no documentation. If you want to use the ProgressDialog constructor directly (as you must in order to subclass it), you must do this instead:

ProgressDialog pd = new ProgressDialog(this);
pd.setTitle("Please wait");
pd.setMessage("working...");
pd.setCancelable(true);
pd.show();

Note that the no-arg show() method used here is an instance method inherited from the Dialog class. The resulting ProgressDialog may indeed be canceled.

StackOverflow indicates that ProgressDialog has been a headache for more than a few developers.

So, like Roman said, use ProgressBar instead. Or if you don’t, make sure you’re using ProgressDialog in such a way that it can in fact be dismissed.

Posted in Android, Headsmack | Leave a Comment »

GWT 2 upgrade almost painless

Posted by David Chandler on January 13, 2010

I took the plunge and upgraded my Google Eclipse plugin and SDKs to GWT 2 using the normal Eclipse update mechanism. The new development mode threw me for a bit of a loop, but that’s the only problem so far. The GWT 2 docs say that the browser will automatically prompt you to download the Google Web Toolkit Developer plugin, but that wasn’t happening for my existing GWT project, only new ones.

The solution was simply to delete the generated app directories under the war folder, and clean and rebuild the project. Then I was prompted to download the plugin as expected, and the browser makes the connection to Eclipse so I can view the GWT logs.

So far so good. I’m anxious to try out the new UIBinder templating and hopefully simplify page layout issues…

Posted in Google Web Toolkit, Headsmack | Leave a Comment »

GWT layout gotcha

Posted by David Chandler on January 12, 2010

I previously wrote about GWT layout with HTML and CSS. One gotcha I’ve found is that you must be careful not to attach a widget to a DIV nested inside a DIV that is attached to a widget. By way of negative example, consider this HTML:

<div id="main">
	<div id="app">
		<div id="detail_header"></div>
	</div>
</div>

Because the detail_header DIV is nested inside the main DIV, this will fail:

		RootPanel.get("main").add(contentContainerPresenter.getDisplay().asWidget());
		RootPanel.get("detail_header").add(userPresenter.getDisplay().asWidget());

The error message is not particularly obvious, which is why I wrote this post:

[ERROR] Uncaught exception escaped
java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list
at com.google.gwt.user.client.ui.RootPanel.detachOnWindowClose(RootPanel.java:122)

The solution is simply to untangle the DIVs by making them siblings instead of nested:

<div id="main">
	<div id="detail_header"></div>
	<div id="app"></div>
</div>

Posted in Google Web Toolkit, Headsmack | 2 Comments »

GWT-RPC serialization gotchas

Posted by David Chandler on November 23, 2009

In gwt-dispatch, Action and Result classes extend java.io.Serializable; however, I have  bumped up against this error a few times:

Type 'com.your_company...' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded.

I get this error for one of two reasons, and wanted it on my blog so I can search it next time 🙂

1. I forgot to include a no-arg constructor.

2. The type of one or more class fields in the Action or Result class is not Serializable (usually a domain object for which I’ve forgotten to implement Serializable).

As a last resort, delete the *.gwt.rpc files in your war/app directory, clean and rebuild. But the problem is usually one of the above…

Posted in Google Web Toolkit, Headsmack | 4 Comments »

Weird serialization error in AppEngine

Posted by David Chandler on November 21, 2009

My previous post discussed a very cool way to do background processing in AppEngine using Deferred.defer. Unfortunately, the AdminEmailTask example I posted results in a cryptic error when the task is dequeued and the Deferred servlet attemps to deserialize it:

com.newatlanta.appengine.taskqueue.Deferred deserialize: invalid type code: 00

After nearly a day’s worth of experimentation, I am really weirded out by what I’ve found: the problem seems to be the name of the private field “msgSubject” in AdminEmailTask. I tried shorter names, longer names, and other names without any problem. I changed the class name, moved it into a different package, and generally pulled my hair out until I simply tried changing the name of the field. At first, I thought it was this JDK bug, but I wasn’t using an array type. Nevertheless, I subclassed ObjectInputStream and overrode the resolveClass method as per the bug’s workaround, only to find out that AppEngine’s implementation of ObjectInputStream doesn’t call the overridden resolveClass and throws a security exception on enableResolveObject(true).

I can only guess that the field name “msgSubject” results in a binary sequence that is somehow special to AppEngine’s implementation of ObjectInputStream, or perhaps it’s a bug in the JDK.

At any rate, if you get the java.io.StreamCorruptedException with invalid type code: 00, try renaming your class fields! I really, really hope I’m mistaken about this.

Posted in AppEngine, Headsmack | 1 Comment »

Tips on organizing GWT modules

Posted by David Chandler on November 19, 2009

My current project is at the point where I’m starting to work on an administrative UI. I wanted to package it as a separate GWT module in order to not clutter up the main application module. There is some code such as the domain model that is shared between the main app and the admin code, so the question is how to organize the modules in order to share code between them.

My first attempt was to have the admin module simply inherit the main app module named ROA in admin.gwt.xml, like this:

	<inherits name="com.roa.app.ROA" />

This had two undesired results:

  • Both modules declare an entry-point, so GWT tries to load both, beginning with the inherited module.
  • At GWT compile time, all the code from the inherited module was duplicated under the admin module in the war structure.

My next attempt was to have the admin and app Java packages each point to a third sister package called “common” containing the domain model and other common code. Java is happy with this, but in order for GWT to compile the common code into JavaScript, you must make it a module. So now there are three packages, each with its own module:

admin.gwt.xml
app.gwt.xml
common.gwt.xml

Admin and app each have entry points and inherit the common module, which does not define an entry point. This works fine.

In the common module, I use the source tag to include multiple directories instead of just the default client directory. Note that if you specify one or more source directories, GWT no longer compiles the client directory by default, so you have to explicitly include it, as well:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.1/distro-source/core/src/gwt-module.dtd">
<module>
	<inherits name="com.google.gwt.user.User" />

	<source path="client" />
	<source path="domain" />
	<source path="presenter" />
</module>

Also, I moved the “public” directory containing CSS and images from the admin and app packages into the common module, and discovered that GWT does not create a “common” directory in the war, but rather copies the contents of the public folder from the inherited common module into both the admin and app module directories. That’s OK, though, as my CSS and images now exist in only one place in source control.

A final note: thank goodness for Eclipse refactoring tools. The easiest way to move a package (say, com.roa.app.domain to com.roa.common.domain) is to select it in the Project Explorer, then right-click, Refactor, and Rename… It’s a bit non-intuitive to use Rename rather than the Move command, but the latter appears to work only for moving packages to another project or source folder, whereas rename allows you to “move” it within the current source folder. Eclipse automatically fixes all the package and import declarations in affected code (whew!).

Posted in Eclipse, Google Web Toolkit, Headsmack | 14 Comments »

Don’t ever do this in GWT

Posted by David Chandler on October 16, 2009

		<div id="something" />

This cost me a night and a day in the deep. It seems to freak out the GWT DOM class such that subsequent calls to it for other IDs fail, in my case causing the screen to vanish entirely. This works fine:

		<div id="something"></div>

Posted in Google Web Toolkit, Headsmack | 4 Comments »

gwt-presenter Hyperlink gotcha: URL in address bar getting wiped out

Posted by David Chandler on October 8, 2009

Just a quick note in the Headsmack department related to navigation between views with gwt-presenter: if you attach a ClickHandler that fires a PlaceRequestEvent to a Hyperlink, but forget to supply the history token, the browser will correctly navigate to the requested Place; however, the placeId and any parameters on the URL will immediately be wiped out in the browser address bar. The reason is that after the ClickHandler fires, GWT replaces the URL in the address bar with the history token from the Hyperlink, which, in the example below, is empty because it’s never set.

		// Don't do this
		Hyperlink hyperlink = new Hyperlink();
		hyperlink.setText("click here");
		hyperlink.addClickHandler(new ClickHandler()
		{
			@Override
			public void onClick(ClickEvent event)
			{
                eventBus.fireEvent(new PlaceRequestEvent(placeRequest));
			}
		});

This is a case of making it too hard (or more likely, accidentally leaving the ClickHandler in place when you decide to try a Hyperlink instead of a Button). Thanks to the gwt-presenter PlaceManager, which listens for History ValueChangeEvents, all you need is this:

		Hyperlink hyperlink = new Hyperlink("click here", placeRequest.toString());

That’s so clean it makes me want to use Hyperlinks everywhere.

See also a previous post on this topic.

Posted in Google Web Toolkit, Headsmack, Model-View-Presenter | Leave a Comment »

gwt-dispatch and com.google.gwt.user.client.rpc.SerializationException

Posted by David Chandler on October 2, 2009

I’d written a new gwt-dispatch ActionHandler with corresponding Action and Result classes and was getting the above exception. The cause turned out be very simple: Action and Result classes implement java.io.Serializable and GWT-RPC therefore requires that they have an empty constructor. So when you get the yellow squiggly in Eclipse that prompts you to generate a serial ID, add an empty constructor, too, and save yourself some grief.

Posted in Google Web Toolkit, Headsmack, Model-View-Presenter | Leave a Comment »

 
%d bloggers like this: