Handling Android 2.3 WebView’s broken AddJavascriptInterface

(Apologies in advance to my normal readers for this technical topic.)

The Google Android team released the Android 2.3 (“Gingerbread”) SDK two days ago, to much fanfare. This has sent the tech blogging world into a publishing frenzy, as it usually does. However, a potentially disastrous bug has surfaced that could crash literally thousands of apps in the Android Market immediately after opening the app.

The problem is described succintly here:
http://code.google.com/p/android/issues/detail?id=12987
In short:
Many apps show all or part of their UI with embedded WebViews that can render HTML.
Those WebViews make use of a great feature that bridges JavaScript (in the HTML) to the native Java code that “surrounds” the WebView.
This bridge is completely broken in Android 2.3. Trying to make even a basic call breaks the WebView immediately and crashes the app.

I believe members of the Android team are aware of the problem, and from early reports, it does not affect the Nexus S (the first Android 2.3 phone). This doesn’t really help those of us working against the emulator, however.

Here is a simple solution to work around this.

1.) In onCreate, check to see if the bridge is broken, and add the JavaScript interface only if not broken.


// Determine if JavaScript interface is broken.
// For now, until we have further clarification from the Android team,
// use version number.
try {
if ("2.3".equals(Build.VERSION.RELEASE)) {
javascriptInterfaceBroken = true;
}
} catch (Exception e) {
// Ignore, and assume user javascript interface is working correctly.
}

// Add javascript interface only if it's not broken
if (!javascriptInterfaceBroken) {
webView.addJavascriptInterface(this, "jshandler");
}

2.) Create a WebViewClient that passes in a new JavaScript object with the same name as your JavaScript interface object.


@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
finishLoading();

// If running on 2.3, send javascript to the WebView to handle the function(s)
// we used to use in the Javascript-to-Java bridge.
if (javascriptInterfaceBroken) {
String handleGingerbreadStupidity=
"javascript:function openQuestion(id) { window.location='http://jshandler:openQuestion:'+id; }; "
+ "javascript: function handler() { this.openQuestion=openQuestion; }; "
+ "javascript: var jshandler = new handler();";
view.loadUrl(handleGingerbreadStupidity);
}
}

NOTE: for each of the Javascript-to-Java functions that you use, you will need to add a new Javascript function and pass it in as part of the loadUrl, like the defined below.

"javascript:function openQuestion(id) { window.location='http://jshandler:openQuestion:'+id; }; "

3.) In the same WebViewClient, override the URL handling portion to handle the URLs defined in step 2. After catching the URL, parse out the function and parameters, then use reflection to actually call the method.


@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (javascriptInterfaceBroken) {
if (url.contains("jshandler")) {
// We override URL handling to parse out the function and its parameter.
// TODO: this code can only handle a single parameter. Need to generalize it for multiple.

// Parse out the function and its parameter from the URL.
StringTokenizer st = new StringTokenizer(url, ":");
st.nextToken(); // remove the 'http:' portion
st.nextToken(); // remove the '//jshandler' portion
String function = st.nextToken();
String parameter = st.nextToken();
// Now, invoke the local function with reflection
try {
if (sMethod == null) {
sMethod = MyActivity.class.getMethod(function, new Class[] { String.class });
}
sMethod.invoke(MyActivity.this, parameter);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return true;
}
return false;
}

With this solution, you only need to make a few Android code changes and do not need to modify server output.

Comments welcome.

Why Google Hates Android

First, some facts.

Next, my hypothesis: Google wants Chrome OS to beat Android. There are lots of reasons for this.

History: Google’s history is web software, and they excel at quickly creating simple, scalable web applications. Android is native software (i.e. software that is stored and executed on your device), which they historically have eschewed. Consider the Google Voice Desktop App saga. If true, Google pulled a potentially killer desktop product because it was not ‘web’ enough.

Control: Android is almost fully open source, while Chrome OS’s web underpinnings inherently make it closed source* Chrome OS’s user experience is loaded over the wire after Chrome OS gets onto the Internet, ensuring that closed web apps take top billing on the OS. Because Android’s source code is readily available, other developers and device makers can fork it, customize it, even go so far as to rip out Google as the default search engine and drop Yahoo or Microsoft in its place. The same (likely) can’t be done to Chrome OS, because the guts of the operating system are loaded from Google’s servers when you turn the machine on. UPDATE: struck out the incorrect bits. Thanks, Mark.

Economics: Google’s decision to deliver the 30% cut of Android Market app sales to telecom companies, instead of keeping it for itself, results in a lack of incentive for Google to invest in the Android Market. Why would they? They make no money on it. This manifests itself in many ways:

  • Android Market pales in comparison to iTunes and (at least by the screenshot) Chrome’s upcoming Web Store. 2+ years and 100K apps after the first Android phone was released, there is still no web presence (outside of a couple hundred apps) for the Android Market, while the other two have (or will have) robust ways to navigate and discover new apps from your PC.
  • The developer console to the Android Market is plagued with repeated, significant problems. Most recent: developers with multiple apps have not been able to see all of their apps for many days now.

Having built such a success in Android, Google has no choice but to continue building upon it. But that doesn’t mean they need to be committed to it. I believe they will continue to invest the bare minimum to show progress and appease their wireless and handset partners. I believe this will result in the following outcomes:

  1. Google will lengthen Android’s release cycle from every 6 months to every 1 year… oh wait, they have already announced this. Increasing the cycle length reduces the speed at which features and functionality will be built into Android, and allows its competitors to catch up or keep moving past Android’s feature set.
  2. Google’s press/blog entries for Chrome OS will increasingly talk about how it will power phones.
  3. Google will fast-track Chrome OS to try to beat Android on tablet devices. The Galaxy Tab sold a reported 600K units in its first month. While solid, this number is still low enough to allow Chrome OS to supplant Android as the non-Apple dominant tablet OS. Google has to act quickly for this, however, as the momentum behind Android by device makers is very significant.
  4. Having considered Android, and the smartphone space as a whole, ‘conquered’, Google’s senior Android engineers will increasingly be allocated to Chrome OS.
  5. Unless Chrome OS dies out of the gate, future Android releases will be underwhelming in both user features and developer tools.

* Yes, Google released the source code of Chrome OS. However, much like Android, the key bits are either going to be closed-source (GMail, Calendar, Android Market), or hosted on Google’s servers where they are untouchable to outside developers.

Thoughts? Other points? Factual inaccuracies? I’d love to hear from you.

Side box scourge

Ever notice those websites that have “Feedback” in sideways text on the web, driven far and wide by GetSatisfaction? I hate those buttons. They completely ruin the aesthetic that site designers struggle to bring to their web pages, by forcing my eyes to this giant block of text.

That was just the start, apparently. Other sites now are taking it to the next level. They layer increasingly complex Javascript-loaded toolbars onto the page, forcing your laptop’s fan on and bringing scrolling and navigation to a crawl.

The worst I have seen in a while is this site by Brad Feld, a venture capitalist with a fairly popular blog.

I get it – he probably invested in Highlighter and wants to eat his own dog food. But, my god, it makes his page (which is already overly complicated) look like a pile of dog food. Outside of the brilliant XtraNormal video, I’m incredibly confused about where to look next. In fact, the little Highlighter boxes to the top, left and right all faded in after the page loaded and when I moved my mouse, further distracting me from the true content on the page.

Where have all the clean, fast-loading, simple websites gone? Why are they being replaced by battery-chewing, fan-inducing, slow-moving piles of garbage? And, most infuriatingly, why does the “Feedback” or “Highlighter” text have to be sideways?

Craigslist/FCC scam by phone

I received a call on my home line (of which 99% of calls are telemarketers, and I rarely answer). The caller listed himself as “Tom from the FCC”, and he was calling to validate my entry in the Do Not Call list. He had a very thick Indian accent and was talking from a scratchy phone line (clearly VoIP overseas). He said that I would receive a second call right after his with “important account information”, then he would call back.

Tom hung up, then two minutes later I received an automated call. It was a simple call saying “Your Craiglist telephone passcode is “, then it listed a 6-digit number.

Two minutes after that, “Tom” called me back. He asked me to read the passcode from the previous call. I told him to stop trying to scam people. He flustered back with “No, no, you misunderstand me. I’m Tom with the FCC, and I am simply trying to verify your registration in the Do Not Call list”, and asked for that passcode again. I asked him multiple questions:

  • What’s your last name? (answer: “Jericho”)
  • What’s your phone number? (answer: “1-888-CALL-FCC” or something like that)
  • Why are you trying to scam people? (answer, again: “You misunderstand me sir!”)

I hung up the phone at this point. I dialed *69, but as expected, the number is unknown.
I’m surprised he kept trying to convince me. I would expect that, at the first sign I would be hostile, he would hang up and try again with a less suspecting target.

It turns out that this is a derivative of a Do Not Call List scam that has been reported on the Internet. Though, what they are going to do with a Craiglist account, I really have no idea. It seems like a lot of effort for very little gain.

Wall Street actions are a result of incentives

How can the financial crisis be a result of anything other than the incentives created by incomplete regulation and incorrect company structure?

People will always respond to the strongest incentives they see and are able to take on. The strongest incentives are so far-reaching across financial firms and the government:

  • Complete lack of either oversight or transparency of the derivatives market creates the incentive to build supposedly market-neutral bets that are orders of magnitudes larger than what capital reserve requirements dictate
  • Compensation packages that pay bonuses now on trades that can blow up later creates incentives for employees to take risks now; if the house falls down, they will be laid off, but will also be much wealthier.
  • The tacit understanding that the largest banks and hedge funds will be rescued no matter how stupid the actions that got them there to begin with creates the incentive to take on increasingly risky positions. If you aren’t playing with house money, you will be playing with taxpayer money.
  • The SEC’s inability to regulate Wall Street, because Congress told them not to, because they were told that regulation hampers innovation by a Wall Street lobbyist, creates the incentive to continue doing what you are doing, as no one from the government will bother you.

I am sure I am missing probably 3-4 other causes for these incentives, but to me these are the biggest.

The financial regulation bill reaching Congress today is a step in the right directly, but will likely introduce or leave behind holes. This will create additional incentives that financial firms will rush to fill. I don’t know what those holes are, as I haven’t read any part of the bill, but I know they will be picked apart by the blogs I do read (mentioned below).

Any argument that talks about morals (e.g. “Wall Street is too greedy”) is doomed to fail. Spend five minutes with a trader from one of these firms, and economic morals is generally completely lost on them. They wouldn’t be successful traders if this wasn’t the case, as their jobs are to take advantage of these kinds of inefficiency.

This post was inspired by this summary from Russ Roberts on Marginal Revolution, as well as from two years of reading Naked Capitalism and Marginal Revolution

“1. It isn’t “too big to fail” that’s the problem, it’s the rescue of creditors going back to 1984, encouraged imprudent lending and allowed large financial institutions to become highly leveraged.

2. Shareholder losses do not reduce the problem even when shareholders are the executives making the decisions

3. These incentives allowed execs to justify and fund enormous bonuses until they blew up their firms. Whether they planned on that or not doesn’t matter. The incentives remain as long as creditors get bailed out.

4. Changes in regulations encouraged risk-taking by artificially encouraging the attractiveness of AAA-rated securities.

5. Changes in US housing policy helped inflate the housing bubble, particularly the expansion of Fannie and Freddie into low downpayment loans.

6. The increased demand for housing resulting from Fanne and Freddie’s expansion pushed up the price of housing and helped make subprime attractive to banks. But the ultimate driver of destruction was leverage. Either lenders were irrationally exuberant or were lulled into that exuberance by the persistent rescues of the previous three decades.”

(Side note: I use the term Wall Street quite loosely here. In reality, many firms that contributed are not physically on Wall Street, and many that are on Wall Street did not contribute in meaningful ways.)

Leaving a dentist near you…

UPDATE 4/22/2010: And like that, the ridiculous program requirements that Align Technologies put into place has been removed. Fortunately I did not follow through on that short – the stock is up almost double since this program was announced.

ORIGINAL 7/9/2009:

.. Invisalign.

In what could be the dumbest business decision I’ve heard of in a long time, Align Technologies (NASDAQ: ALGN), makers of Invisalign® has decreed that all dentists offering Invisalign must start 10 cases per year and complete 10 CE credits related to Invisalign per year (copy of letter sent to one dentist here).

What this means for the consumer:

  • The consumer experience will undoubtedly improve. Those who truly want Invisalign will now have a limited set of very experienced dentists to choose from.
  • However, competitive pressure may change that – see notes on ClearCorrect below.

What this means for the dentist:

  • The national average for a case is $5,000/year(source). Convincing 10 patients per year to fork over $5,000/year for a truly elective procedure is very, very hard in the vast majority of markets out there. Only the ones that market heavily and whose business consists of a very high percentage of cosmetic dentistry will make this quota.
  • Every dentist who became certified in the past 5+ years was required to pay $1K-2K to become certified. This, combined with a mandatory reduction in services, is going to lead to a large number of very unhappy dentists at this decision (I know a few myself). And, you can be sure that unhappy dentists across the country will do whatever is in their power to keep a patient in the door. A few choice quotes from the online dental community DentalTown:
    • “Absolute idiots IMHO !!! I wonder if they will be refunding doctors certification costs as they decided to change the rules in the middle of the game?”
    • “While there are many doctors that may not submit many cases to Invisalign, I suspect these same doctors talk alot about invisalign and are a terrific advertising/referral source for high volume invisalign offices or orthodontists. I’m sure many of us won’t have very many nice things to say about Align right now.”

What this means for Align Technologies:

  • I would expect that this knocks out 50-75% of their dentists (by number), but only knocks out 10% of revenue in year 1*. They can align sales/admin costs against this expected reduction in revenue to minimize the impact to net income. This, however, does not include the general softness expected in their business due to offering an expensive, elective procedure during a severe recession, which analysts have already identified.
  • Beyond intentionally cutting revenue during the recession, their timing is poor. Between being found as violating patents by one competitor (Ormco Corporation) and seeing another upstart invade their turf (ClearCorrect), they are leaving dentists with plenty of options that are not Invisalign.

How long will they have until this newfound exclusivity takes a toll on their brand strength and share price? I don’t think their 2Q earnings will reflect the change, as the few fringe dentists are likely pushing Invisalign hard to hit their quota, but I would be surprised if they don’t have to lower guidance again in future quarters, partially as a result of this policy.

Comments? Thoughts?

*These are gut-feel numbers, not based on financial analysis.

Migrating Dentrix Image 4.5’s database to another computer

This post is way off-topic for those who read me regularly, but it should be helpful for those looking for this information via a web search.

Our original server was a very old (1999ish), very slow Pentium running Windows XP Professional, Dentrix 11, and Dentrix Image 4.5.
We decided to upgrade, and bought a new Dell PowerEdge server with a Dual Core Intel Xeon processor and Windows Server 2008 64-bit edition.

Installing Dentrix, Image, and the other required applications went fairly smoothly, with only a possible hiccup with installing .NET Framework 1.1, required for Dentrix. I say possible because it was only a warning, and we don’t know if it will manifest into any problems down the road.

After installation came the hard part – moving the data.

  • Pulling the Dentrix data (ledger, chart, schedule, etc.; about 300MB) over was simply a matter of copying the data into the appropriate Data directory.
  • Pulling images (35GB) over took longer, given the amount of data, but it was as simple.
  • Figuring out how to transfer the Dentrix Image SQL Server database, the database that contains a mapping between patients and images, took an absurd amount of time.

I tried:

  • Stopping the SQL Servers on both source (old server) and destination (new server) and copying the .mdf/.ldf files from source to destination. This resulted in Chart showing “Cannot initialize image database”.
  • Using the seemingly-useful DXImage/bin/IDImage application, which ultimately failed.

The key to figuring out was this Microsoft Support article describing moving databases using sp_detach_db and sp_attach_db. To fix,

  • Open a command line on the source and type ‘osql -E -Q’ to get into SQL command line
  • Type:
use master
go
sp_detach_db 'Viper'
go
  • Copy ‘Dentrix\DXImage\MSDE\MSSQL$VIPER\Viper.mdf’ and ‘Dentrix\DXImage\MSDE\MSSQL$VIPER\Viper_log.ldf’ to the same location on the server as ‘Viper_2.mdf’ and ‘Viper_log_2.mdf’
  • Open a command line on the destination and type ‘osql -E -Q’ to get into SQL command line
  • Type:
use master
go
drop viper
go
sp_attach_db 'viper','C:\Dentrix\DXImage\MSDE\MSSQL$VIPER\Viper_2.mdf','C:\Dentrix\DXImage\MSDE\MSSQL$VIPER\Viper_log_2.ldf'
go
  • Make sure to change your firewall settings on your new server to enable SQL Server to access it.

This did it. Oh, how I wish Dentrix Image had better (or any, for that matter) documentation, except for this site which looks like it was written by someone in high school.

UPDATE: In all likelihood, the first method (copy .mdf and .ldf) might have worked had I tried changing the firewall settings sooner!

UPDATE 2: After a massive meltdown of our servers and a long technical session with the good people at Dentrix Image, we learned a few things:

  • Windows Server 2008 is NOT supported for Dentrix Image 4.5. It was practically sheer luck that enabled it to work. Windows XP and (I believe) Server 2003 are the only supported environments. The issue lies with the embedded Microsoft SQL Server used in Dentrix Image itself, which is incompatible with Server 2008.
  • However, since we already migrated Dentrix to Server 2008, and still had our workstations on XP, there is a solution: leave the actual images on our fast new Server 2008, and host the image database itself on a workstation running XP.
  • The caveat here is that both machines must be accessible by network names (e.g. “server1”, “server2”), and not just by IP address (e.g. “192.168.1.10”). So, if I ping “server1”, I would get a proper response. It is beyond the scope of this entry to explain how to make this work, but a hint to get you down that path: static IPs and the hosts file.

To get this hybrid system (image files on “dentrix server”, image database on “idb server”) to work:

  • Install Dentrix Image as a server install on a Windows XP machine. We’ll call this machine “idb server” below.
  • On the old server, run [DXImage]\bin\IDBAdmin
  • Choose Export Database and choose a path. Move the resulting exported database to the idb server.
  • On the idb server, run [DXImage]\bin\IDBAdmin
  • Choose Import Database and choose the file you just copied over.
  • Choose Initialize Database.
  • On the dentrix server, open [DXImage]\images\rtx.con . Change the file to point to the new server’s network name. This is the missing link: workstations will look at this file to figure out where to find the image database.

UPDATE 3: We have posted our backup process for the lowly Windows XP IDB Admin server in a follow-up, Backing up Dentrix Image 4.5’s database.