I /thought/ I knew how to copy a file…

More trials and tribulations on the Android platform – which I love, don’t get me wrong.

I admit upfront that this is very likely my own fault for not knowing the ‘correct’ way to achieve my goal. It also may possibly have to do with some Android 1.5 behavior, as that is the standard I typically use for compatibility on simple apps. Anyway…

Today’s story begins with an xml file. More precisely, an xml file containing an RSS feed - to ‘preload’ an Android application with a backlog of blog posts stored locally on the device.

So, I store the xml file in the /raw folder in Eclipse, and use

rssInputStream = this.getResources().openRawResource(R.raw.feed);

to get the input stream, then proceed to loop through the file, writing to my output file in /data/data/<myPackage>/files/feed.xml (approximately 300kb file) which I will read and write from on future accesses.

It works great, sort of. In the following code to copy the file from the raw resource to my local feed.xml file:

while ((length = databaseInputStream.read(buffer)) != -1)

if the buffer is [1], everything works – but SLOWLY (obviously).

if the buffer is > [1] and < [size of the file], the file gets truncated in a weird (but consistent) position no matter what the buffer size is. It truncates in the same spot with different buffer sizes, so it doesn’t seem to be a buffer size/loop/overflow condition.

if the buffer == [size of the file], it works and is fast

if the buffer > [size of the file], it all gets copied, but I have to trim the end whitespace from the file or I get parsing problems later.

I swear I have tried a million different combinations of loop and copy conditions, and all seem to result in the same behavior. I even tried doing an extra read/write after the loop just to make sure there was nothing left behind in the stream…no dice. I tried at least 2-3 completely separate code examples to accomplish this…same result.

So, for now, since I know the size of the file I am deploying, I’m cheating and using buffer == size of file

And this serves as my reminder/documentation the next time I want to publish an updated version of the app with a new raw file…REMEMBER TO UPDATE THE BUFFER SIZE!




Android and ‘file://’ and ContentProvider, Oh My

So tonight I ran across the need to load ‘local’ html files that I am generating on-the-fly from XML files into a WebView. It turns out that over the last several releases of Android, Google has actually made this MORE difficult to do. Originally it seems that file://<path> links worked in a WebView loadUrl() call, then that was removed. Then there was a different workaround, and THAT was removed.

Anyway, the answer if you NEED to do this is to use a custom ContentProvider. Rather than bore you with my own tweaks to the code, I’ll just point you to the best samples I found on short notice.




Java as a second language – part 1,228,325

Every time I start to think this java/Android coding is like riding a bicycle (which I fell off of sometime in early 2002), I get brought back to reality.

This weekend I discovered a couple of things, more slowly than I care to admit:

1. Parsing XML on Android is slower than…well, let’s just say it’s slow. I didn’t really believe what I was seeing at first, so I started looking around. Looks like I may go back to my alternate model using SQLite.


2. Java XML – getLocalName vs getNodeName – Although I had a basic grasp of the fundamentals of XML, I didn’t really have to deal with the real intricacies of XML schemas until I started working with BizTalk. At that point I learned all about ‘local’ names and erring on the side of caution burned me in this case. So I was trying unsuccessfully to ‘getLocalName’ in Java code but the result was always ‘null’. Lo and behold – ‘getLocalName’ seems pretty useless. Reference the following:

Here is what SHOULD happen IMHO.


And HERE is (I assume) what actually happens in my case returning NULL in all cases, even though the Eclipse debugger shows clearly a populated ‘localName’ property in my ‘variables’ window. If schemas have not been explicitly enabled/created/invoked via some magical voodoo, getLocalName won’t do anything.