11-02-2009 03:20 AM
InputStream class cannot implement Seekable in principle. This is because it's an abstract superclass of the whole input stream hierarchy. If RIM were to add "implements Seekable" to InputStream class, they would break all subclasses (including those from third-parties) that extend InputStream, not to mentioned that java.io.InputStream does not implement Seekable in standard Java.
When you obtain a (n instanceof) FileConnection (or any other stream connection for that matter), it can return you an instance of InputStream when you invoke openInputStream. Now, this instance will never be of class/type InputStream. It will be a subclass of InputStream. That subclass may or may not implement Seekable. These subclasses in most cases are internal RIM implementation classes and they won't be listed in javadocs anyway. In fact, you don't want them listed in javadocs to maintain nice design, encapsulation, and the so forth.
When you say the "instanceof" test works on the newest JDE, it probably means that you can write code that checks whether the input stream object returned by FileConnection.openInputStream() is "instanceof Seekable". Your code can then branch into two: (1) the case where the input stream you obtained is not instance of Seekable (e.g., pre-5.0.0) and hence easy random access is not available, and (2) the case where the input stream you obtain is instance of Seekable (e.g., latest 5.0.0 builds) and you can cast the input stream to Seekable and invoke setPosition and getPosition.
11-02-2009 05:06 AM
Yes, I'm aware of this.
I'd rather a subclass be exposed to the end user that explicitly implements Seekable, that is my preference, but there are policy decisions to doing this or not doing this, like you say.
11-02-2009 06:40 AM
Great news to hear. You said that it was in 5 rev 4, do you know what that equivilant is for Eclipse Component Packs? When I check my most recently installed version it is 18.104.22.168. Is that 5 rev 4?
11-02-2009 03:45 PM
So, how would a javadoc-ed subclass implementing Seekable be better than a non-javadoc-ed subclass implementing Seekable? You'll still have to conditionally cast the input stream returned by openInputStream to either the javadoc-ed subclass or the Seekable interface. The second options looks simpler and cleaner. You still probably won't be able to instantiate the javadoc-ed subclass yourself, meaning the only way to obtain such an object would be as before -- via FileConnection.openInputStream().
11-02-2009 04:37 PM
Here's a small example. If there are seekable InputStreams and non-seekable InputStreams, which, at the moment, seems to be the case, then the only way one can distinguish them is by doing an instanceof check.
Fine; when one now wants to perform operations on seekable InputStreams in a class, say, suppose by having an InputStream instance variable, one is faced with the following:
* performing the instanceof check in the constructor and throwing an exception there if not seekable -- not very nice
* disallowing instantiation of the InputStream in the constructor, creating a mutator, and throwing an exception there -- maybe, but it's awkward
* having each of the methods throw exceptions if the stream is not seekable -- more awkwardness
* having the constructor/mutators accept a Seekable -- maybe, but then there's casting involved (and maybe some reflection involved depending on the application or with different streams)
All this mess just goes away if there is a SeekableInputStream subclass, for example. Attempting to use non-seekable InputStreams would be caught at compile time. Knowing how to seek within the stream becomes implicit -- the subclass implements the interface and we all know about it.
Look, there are disadvantages and advantages to both approaches; like I've said, it's more a policy decision rather than a firm technical decision to do it one way or the other, so it's not too useful to argue to the toss much here.
Of course, the entire problem I had could have been solved by better documentation. "Implemented by some InputStreams and Readers so the read/write position can be adjusted." doesn't tell the reader much -- which InputStreams and Readers? -- for example.
10-10-2010 05:17 AM
I'm finding another problem here. The InputStream returned from Connector.open() sometimes passes the "instanceof Seekable" test, and sometimes it doesn't. So far, it appears to pass the test on Storm and Storm 2 devices, with 5.0 installed. On Tour and 9650 models, however, with OS 5.0, the InputStream appears not to be Seekable?
What's going on?
Can someone from RIM comment on this? Are we just hacking through private APIs here? Is Seekable even something that RIM intends to be usable by 3rd-party developers? If so, we need documentation on what is Seekable and what isn't. You really can't write code conditionally testing everywhere, and hoping that each platform will allow your code to function.
Just to be specific, on Storm/Storm 2, the InputStream returned from Connector.open (on a file I have stored under /store/home/user/ProjectName) is a net.rim.device.cldc.io.file.PosixFileInputStream, which passes "instanceof Seekable".
On 9630/9650, the InputStream I get with the same code, also on a file stored under /store/home/user/ProjectName, is of type net.rim.device.internal.io.store.ContentStoreInput
10-10-2010 08:10 AM - edited 10-10-2010 08:14 AM
Thanks for the details, n8r0n! This looks "interesting". My hunch (pure speculation, in fact) is that only files stored on filesystems backed by an SD Card will always be seekable. You are accessing files in the "internal store" which may or may not be backed by an SD Card. For example, the "internal store" of Bold 9000 is backed by an internal SD Card, whereas other phones may not necessarily have the same implementation. As far as I know, internal stores backed by SD Card can be made available via USB Mass Storage, whereas those not backed by SD Card cannot. To test this hypothesis, see if you can make the "internal store" visible on your PC over USB Mass Storage on the devices you mentioned.
10-10-2010 04:01 PM
That is interesting. Did you test on both with the same program or did you simply throw in a "instanceof Seekable" in an already existing program? Does getResourceAsStream return a Seekable instance?
10-11-2010 01:44 AM
Well, here's what I found out. First, to answer your questions (rcmaniac25), yes, I was using the exact same code on Storms vs. Bold/Tour. I stepped through in the debugger to make sure the same exact code paths were being followed.
getResourceAsStream() returns an InputStream, but it NEVER seems to be Seekable. Thus, even on Storms, what I have to do is copy my bundled resource to another location, so I can open it up with Connector.open(). This, by itself, is bad, but I'd already committed to making that sacrifice (which just wastes the users' storage, having to have two copies of the file).
But, after I copied the bundle resource, then re-opened the file with Connector.open(), it yielded a Seekable InputStream (via FileConnection.openInputStream()) on the Storm devices.
Anyway, the suggestion about the SDCard seems to have worked. At least on the desktop simulators (I don't have a real Bold/Tour), saving my file to file:///SDCard/ProjectName, and then opening it, gives me a Seekable object, on 9530/9550/9630/9650 devices.
I don't really want to do this (bad design to have a file that my application needs on removable storage), and I really don't want to do this without an explanation of why it seems to work this way. Is the next device that comes out going to behave this way, or are we just stuck conditionally testing every InputStream we get, and constantly copying our bundle resources to every available storage location, until we find one that appears to support seek operations?
I hope this approach seems ridiculous to all involved.