Android: Open dynamically created file with ContentProvider

If you have asked yourself how to can return a handle to a temporary file from an own Android ContentProvider implementation, here is a good solution I found at tomgibara.com by utilizing the behavior of the underlying linux file system:

The basic scenario is this: You have implemented a ContentProvider and you want to use it to return something that is too big to fit into a cursor, say an image. It’s clear from the relevant Android platform javadocs, though perhaps not from the general ContentProvider documentation, that this is done by implementing openFile and returning a ParcelFileDescriptor.

But now suppose that the image resource is being rendered on the fly. How do you implement openFile?

As per the contact of openFile you need to return a ParceFileDescriptor which means that the resource must be returned via an open file (or possibly a socket, which we’ll ignore). This means that the image must first be written to a file, which is then opened as a ParceFileDescriptor. The interesting question here is when do you delete the file?

You can’t wait until the calling process has finished reading the file because (a) you won’t get notified when that occurs and (b) it may never exhaust the stream anyway. You can’t rely on the calling process to delete the file for you either, also, the whole idea behind wrapping the resource in this way is to guard it from direct access by other processes. You could delete the file after a fixed time period — assuming that the caller will have finished reading the file by that time. But this is unnecessarily complex, because the answer turns out to be very simple:

You delete the file immediately after you’ve opened the ParcelFileDescriptor but before you return it from the openFile method.

The reason this works is down to the way that Linux filesystems operate: directories maintain links to files, when a process opens a file a new link is created, closing a file or removing it from a directory removes a link. When there are no links to a file, the file is deleted.

So by opening the file in our application, we create a link to it. Then ‘deleting’ the file actually unlinks it, but the file won’t really be deleted until the file descriptor is discarded (ie. the last link is removed). This will happen automatically at some point after the calling application has finished accessing the file and any associated ParcelFileDescriptor objects have become garbage.

Read the full post at Returning dynamically generated resources – Parentheticals & Excursions.

Android Fragmentation

Google announced on its Android Developers Blog that they are now providing a device dashboard showing the distribution of the Android version accessing the Android Market (later on also including hardware characteristics of devices).

As a developer, I often wonder which Android platforms my applications should support,especially as the number of Android-powered devices grows. Should my application only focus on the latest version of the platform or should it support older ones as well?

To help with this kind of decision, I am excited to announce the new device dashboard. It provides information about deployed Android-powered devices that is helpful to developers as they build and update their apps. The dashboard provides the relative distribution of Android platform versions on devices running Android Market.

In summary, Android 1.5, 1.6, and 2.0.1 are the 3 versions of the platform that are deployed in volume. Our goal is to provide you with the tools and information to make it easy for you to target specific versions of the platform or all the versions that are deployed in volume.

We plan to update the dashboard regularly to reflect deployment of new Android platforms. We also plan to expand the dashboard to include other information like devices per screen size and so on.

Don’t get me wrong: the data is very interesting. However, it strongly reminds me on the situation on Windows, where still about 30% of the users use Windows XP. Having such a big fragmentation of OS versions really forces you to either make big compromises and build your application only using the features of the lowest OS version or to make your application adapt to the OS version it is running on. The later one adds a lot of trouble in development efforts, testing and bug fixing.

Still, it will be interesting to see how the fragmentation of Android devices evolve and how this will influence the attraction of developers providing Apps for the Android OS. Of course, having developers focusing only on certain Android OS versions and/or hardware characteristics could also make the hardware vendors streamline their hardware specs and OS versions. Selling Android devices which show only very few apps on the Android Market might not sell so well after all.