Tuesday, August 17, 2010

Problem with Eclipse/Android/Helios/XML editing

If you're seeing errors like this in Eclipse/Helios when you're editing an Android resource file, you're hitting this Eclipse bug.  The workaround is to go to Preferences > XML > XML Files > Editor and turn off Use inferred grammar in absense of DTD/Schema.
Problems occurred when invoking code from plug-in: "org.eclipse.jface".

at org.eclipse.wst.xml.core.internal.document.ElementImpl.getDefaultValue(ElementImpl.java:259)
at org.eclipse.wst.xml.core.internal.document.ElementImpl.getAttributeNS(ElementImpl.java:329)
at com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode.getShortDescription(Unknown Source)
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiModelTreeLabelProvider.getText(Unknown Source)
at org.eclipse.jface.viewers.WrappedViewerLabelProvider.getText(WrappedViewerLabelProvider.java:108)
at org.eclipse.jface.viewers.WrappedViewerLabelProvider.update(WrappedViewerLabelProvider.java:164)
at org.eclipse.jface.viewers.ViewerColumn.refresh(ViewerColumn.java:152)
at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:934)
at org.eclipse.jface.viewers.AbstractTreeViewer$UpdateItemSafeRunnable.run(AbstractTreeViewer.java:102)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)
at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:1014)
at org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable.run(StructuredViewer.java:481)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)
at org.eclipse.jface.viewers.StructuredViewer.updateItem(StructuredViewer.java:2141)
at org.eclipse.jface.viewers.AbstractTreeViewer.updateChildren(AbstractTreeViewer.java:2689)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefreshStruct(AbstractTreeViewer.java:1867)
at org.eclipse.jface.viewers.TreeViewer.internalRefreshStruct(TreeViewer.java:721)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1842)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1799)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1785)
at org.eclipse.jface.viewers.StructuredViewer$7.run(StructuredViewer.java:1487)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1422)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:403)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1383)
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1485)
at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:537)
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1444)
at org.eclipse.jface.viewers.ContentViewer.setContentProvider(ContentViewer.java:252)
at org.eclipse.jface.viewers.StructuredViewer.setContentProvider(StructuredViewer.java:1641)
at org.eclipse.jface.viewers.AbstractTreeViewer.setContentProvider(AbstractTreeViewer.java:2317)
at org.eclipse.jface.viewers.TreeViewer.setContentProvider(TreeViewer.java:972)
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.changeRootAndDescriptors(Unknown Source)
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.createTreeViewer(Unknown Source)
at com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock.createMasterPart(Unknown Source)
at org.eclipse.ui.forms.MasterDetailsBlock.createContent(MasterDetailsBlock.java:161)
at org.eclipse.ui.forms.MasterDetailsBlock.createContent(MasterDetailsBlock.java:142)
at com.android.ide.eclipse.adt.internal.editors.resources.ResourcesTreePage.createFormContent(Unknown Source)
at org.eclipse.ui.forms.editor.FormPage$1.run(FormPage.java:152)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.forms.editor.FormPage.createPartControl(FormPage.java:150)
at org.eclipse.ui.forms.editor.FormEditor.pageChange(FormEditor.java:471)
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.pageChange(Unknown Source)
at org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1067)
at org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:603)
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.selectDefaultPage(Unknown Source)
at com.android.ide.eclipse.adt.internal.editors.AndroidEditor.addPages(Unknown Source)
at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138)
at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348)
at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670)
at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2863)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2768)
at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2760)
at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2711)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2707)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2691)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2682)
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651)
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610)
at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:365)
at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:168)
at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:229)
at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:208)
at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:274)
at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:250)
at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:373)
at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:526)
at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48)
at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:845)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175)
at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:843)
at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1131)
at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1235)
at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:264)
at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:258)
at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:298)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3776)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1367)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1390)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1187)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3622)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3277)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)

Tuesday, June 29, 2010

A proguard builder for Scala + Android

I just put up code for an Eclipse builder to make it simpler to build Scala projects for Android.


It's still pretty rough, but it gets the job done.

Saturday, June 19, 2010

Eclipse plug-ins not showing suggested templates

If you’re new to developing Eclipse templates, and you’re wondering why you’re not seeing a list of templates when you create your new project, make sure you check “This plug-in will make contributions to the UI” in this dialog:
If you don’t check that, you’ll see:
Instead of:

Thursday, June 10, 2010

Comparing Microsoft and Google

Interesting comment on Microsoft vs Google (what it's like to work there) on the
Mini-Microsoft blog.

Look for the comment starting with:

>> And how do you compare GOOG to MSFT?

It's not black and white, there are advantages and disadvantages to both.


Wednesday, June 9, 2010

Tuesday, June 8, 2010

If you're trying to use jruby on rails, and you see an error like this:
GEM_HOME=~/.jrubygem jruby -S rake db:create:all
(in /private/tmp/fnord)
!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.
rake aborted!
no such file to load -- mysql

(See full trace by running task with --trace)

The solution is to run script/generate jdbc:

GEM_HOME=~/.jrubygem jruby -S script/generate jdbc
      exists  config/initializers
      create  config/initializers/jdbc.rb
      exists  lib/tasks
      create  lib/tasks/jdbc.rake
See Nick Sieger's blog for more detail.

Tuesday, May 25, 2010

Windows 7 Mobile Operating Thingy for Whatsits - does anyone care?

I was at Google IO last week.  Talk about iPhones was everywhere - people thinking about how the Android vs iPhone battle was going to play out.

Windows 7 Mobile Operating Thingy for Whatsits (or whatever they're calling it these days) wasn't talked about.  Not at all.  Zero. Nada.

The Kin?  Again, nothing.  Crickets.

I hear there was trivial shakeup at Microsoft today.  Whatever.

Do the people at Microsoft understand how bad things are?  Sure doesn't seem like it.

Monday, May 24, 2010

Android carriers and phones - Sprint, TMobile, Verizon, ATT, Droid, Evo, iPhone, Nexus One

We're just finishing up a trip to San Francisco, Los Angeles and San Diego. Between me and my fiancee we're carrying around four cell phones (thanks to giveaways at Google IO):

  • Droid/Verizon
  • HTC Evo/Sprint
  • iPhone 3G/ATT
  • Nexus One/TMobile (my fiancee's phone)
Our reactions to the carriers and phones so far:

Droid/Verizon: works great, works everywhere, but you need a forklift to carry this thing around. The Droid is clearly an engineering prototype that someone from marketing stole from the lab. It's just not a shipping product, no way, no how.

However, since I'm a geek, carrying around the engineering prototype hasn't been that bad.  When I was carrying around the Droid and the iPhone 3G, I'd almost always pull out the Droid.  I'd really only pull out the iPhone for UrbanSpoon.

HTC Evo/Sprint: The new hotness.  The screen is bigger than my laptop.  It's fast.   It's got some lame software on it called "Sense" - sometime soon I'll need to figure out how to disable it, but it's only mildly annoying so far.

Sprint has been surprisingly good - no coverage problems in urban areas so far, and very good coverage on the train between LA and San Diego (with some dropouts where geography was pretty obviously terrible - Camp Pendleton for one).

iPhone 3G/ATT: I'd like to tell you about ATT's coverage, but I almost never pull the iPhone out of my pocket.  It feels archaic at this point.

Nexus One/TMobile: Very nice phone, but as far as we can tell TMobile isn't actually in the business of providing wireless connections to cell phones with any sort of reasonable coverage.  Just pathetic.  TMobile isn't worth considering as a provider.

Wednesday, May 12, 2010

Android - loading a javascript file from a web page needs internet permission

If you're trying to include javascript in an android.webkit.WebView view with a standard script tag like this:
<script language="javascript" src="demo.js" />
You need to add internet permissions to your manifest:
<uses-permission android:name="android.permission.INTERNET" />
Doesn't seem to matter that the file is local.

Tuesday, April 27, 2010

Liking the Droid a bit more

After using the Droid for a bit, I'm feeling more charitable.

Just have to think of it as an engineering prototype.  It's not really a device you'd expect people to pay money for - it's far too clunky for that.  But as a limited production device just for developers, it's fine.

I'm carrying it and my iphone around now (it's a pain), and I find that I pull out the Droid far more often.  The web browsing experience is just that much better than the iPhone.

Thursday, April 22, 2010

New Droid arrived

Got my new Droid a few minutes ago.

First impression: the thing feels like a tank.  Very industrial.  Not at all a warm and fuzzy feeling like the Nexus One or my iPhone.

And the slideout keyboard is the definition of epic fail.  Useless, probably adds quite a bit of weight and complexity to the phone.  Just wrong, wrong, wrong.  This phone should never have left the lab.

I suspect that I did this in the wrong order.  You need to experience a Droid before you play with a Nexus One.  Had I done that, I might have been more impressed.

It's good to have a Droid though, since they're apparently the most popular Android device.  Good to have around for testing.  But I pity the people who have to use this as their primary device.

Friday, April 2, 2010

ipad - thumbs down

I'm on a ski trip with a friend (teenager, from San Diego, the cultural capital of the world). His unsolicited comments on the ipad:

It's just a giant ipod touch.   Go buy yourself a computer with that. Like seriously what's the point of that? Don't buy the ipad. Piece of ..."

I'm with him. If the thing were seriously less expensive, it'd be interesting. It's not.

Now, I should probably add that he's now chanting "looser" since I'm taking too long to type up this entry, so maybe I'm not so fond of his opinions after all...

Monday, March 22, 2010

jruby and mkdir problems with gems

If you see an error like this when you're installing gems:
GEM_HOME=/Users/james/.jrubygem GEM_PATH=/Users/james/.jrubygem jruby -S gem install -V activerecord-jdbcmysql-adapter rails

ERROR:  While executing gem ... (SystemCallError)
  Unknown error - mkdir failed
Make sure you don't have a ~/.gem directory with bad permissions. jruby wanted to use that directory for something even though I had specified a different GEM_HOME.

Sunday, March 7, 2010

HTML with the F# question mark operator

I needed to create some HTML from F#.  I wanted something where the F# looked something the the results, and I didn’t have any need for anything other than the basics (tags, attributes, text contents).

I had seen a few posts talking about the question mark operator and hadn’t used it yet.  It seemed like the obvious candidate – it means you can put tags into code without writing a whole lot of support for each and every tag name you’re going to need.

What I ended up with is syntax that looks like this:

let h = com.restphone.Qml.Builder()

let exampleWithATable =
  let a =
    h?table <- [
      h?tr <- [
        h?td <- "one"
        h?td <- "two"
  printExample "a table" a
// a table
// -----
// <table>
//   <tr>
//     <td>one</td>
//     <td>two</td>
//   </tr>
//   <tr />
// </table>

The elements after the question marks are just turned into strings then passed to a function that turns them into nodes in the HTML tree. Nesting nodes uses the <- operator followed by a list of items that can be:

  • Strings get turned into content
  • Two-element tuples are turned into key-value attributes
  • Nodes (using the same h?sometag syntax)

I like the way the syntax ends up looking quite a bit like the HTML it’s producing as the final output.

A couple more examples:

let exampleWithAttributes = 
  let a1 = 
    h?ol <- [
      h?li <- [
        "class", "formattedList"                   // Two-element tuples are attributes
        "something", "something & else"           
        {name = "class"; value = "listItemStyle"}  // Or you can use an actual Attribute object
        "this should have escapes: & < >"          // content will be escaped
      h?li <- "second"
  printExample "list items with content and attributes" a1
// list items with content and attributes
// -----
// <ol>
//   <li class="formattedList" something="something &amp; else" class="listItemStyle">this should have escapes: &amp; &lt; &gt;</li>
//   <li>second</li>
// </ol>

let exampleWithASpanInContent =
  let b =
    h?foo <- [
      "content text"
      h?span <- "something in a span"
      "more text"
  printExample "content containing a span" b
// content containing a span
// -----
// <foo>content text<span>something in a span</span>more text</foo>

And here’s the code:

namespace com.restphone.Qml

open System.Xml

// Name-value pairs
type Attribute =
  {name: string;
   value: string}

type Element =
  {tag: string;                   // The html tag; table, p, etc
   attributes: Attribute list;
   children: Node list}
and Node =
  | Element of Element
  | Content of string

type Builder() =
  static let emptyAttribute = {name = ""; value = ""}

  static let tupleToAttribute (t: System.Tuple<string, string>) =
    {emptyAttribute with name = t.Item1; value = t.Item2}

  static let builder(builder, tag, things: obj list) =
    let rec appendThings (element: Element) (xs: obj list) =
      match xs with
      | (:? Element as nextElement)::t -> appendThings {element with children = (List.append element.children [Element nextElement])} t
      | (:? string as content)::t -> appendThings {element with children = (List.append element.children [Content content])} t
      | (:? List<Attribute> as attrs)::t -> appendThings {element with attributes = List.append element.attributes attrs} t
      | (:? Attribute as attr)::t -> appendThings element ([attr] :> obj::t)
      | (:? System.Tuple<string, string> as p)::t -> appendThings element ((tupleToAttribute p) :> obj::t)
      | [] -> element
      | x -> element
    appendThings ((?) builder tag) things
  static let printAttribute (x: System.Xml.XmlWriter) (attr: Attribute) =
    x.WriteAttributeString(attr.name, attr.value)
  static let printAttributes x attrs =
    List.iter (printAttribute x) attrs

  static let rec printContent (x: System.Xml.XmlWriter) s =
    x.WriteString s

  static let rec printElements x e =
    let pe = function
      | Content c -> printContent x c
      | Element el -> printElement x el
    List.iter pe e
    printElement (x: System.Xml.XmlWriter) e =
      x.WriteStartElement e.tag
      printAttributes x e.attributes
      printElements x e.children
      x.WriteEndElement ()
  static member (?) (a: Builder, tag) =
    {tag = tag; attributes = []; children = []}
  static member (?<-) (a: Builder, tag, things: obj list) = builder(a, tag, things)
  static member (?<-) (a: Builder, tag, content: string) = builder(a, tag, [content])
  static member (?<-) (a: Builder, tag, attributePair: string * string) = builder(a, tag, [attributePair])
  static member (?<-) (a: Builder, tag, attr: Attribute) = builder(a, tag, [attr])
  static member (?<-) (a: Builder, tag, e: Element) = builder(a, tag, [e])
  static member write elements x =
    Seq.iter (printElement x) elements

  static member ElementSeqToString (h: Element seq) = 
    let sw = new System.IO.StringWriter()
    let xtw = new XmlTextWriter(sw)
    xtw.Formatting <- Formatting.Indented
    Builder.write h xtw |> ignore

  static member ElementToString (h: Element) = 
    Builder.ElementSeqToString [h]