Jar Indexing progress bar

Hello,

I am using Jar Indexing to load certain parts of the game at opportune times for the end user.

For example, most of the source (1mb worth or so) is in one JAR, whereas sfx and music are in another (27mb or so).

So they are able to download the basic 1mb app and show an in-game load screen. The problem is, there doesn’t seem to be any callback for when elements inside a jar are loaded from indexing.

Does anyone know a way around this? I’m referencing the audio in a separate thread, but that thread just blocks until the whole 27mb is downloaded. Best I can do right now is a spinner, but some indication of progress would be great.

Thanks for any help,

Jesse

If you know the downloaded size and can wrap the stream you can derive the download speed and indeed a progress bar.
I already did it (in the most inefficient possible way i think).

How do you wrap the stream? Would you mind sharing your code?

Jesse

extend InputStream and overwrite the 3 read(…) methods, then pass the original InputStream in the constructor and delegate the all method invocations to it. Now you can hook some feedback interface onto the InputStream and get notified of read(…) invocations.

Okay, I follow what you are saying. I can do this no problem - however in my calling code, I am not actually “reading” the data into memory. I am simply “touching” it so Jar Indexing decides to download the JAR.

My code looks like:


GetClass().getResourceAsStream(filename);

This is the function that blocks until the JAR is finished downloading. Now I could wrap this in a subclass like you suggest, such as


new WrappedInputStream(getClass().getResourceAsStream(filename));

but this will just block in the same way as before. My overloaded read methods would never be executed.

Jesse

It’s not clear to me why you want to access your resources through a classloader. You can write a custom ClassLoader, that monitors its download progress, but why make it so hard for yourself? Put all the small resources in a JAR, and download the big stuff like music seperately, using URLConnection.getInputStream() and enable caching.

I’m not sure if this is what you’re seeking for, you’re supposed to put the whole input stream in a BufferedInputStream.
I used to dowload .jar in this way :


        final URLConnection connection = src instanceof URL ? ((URL) src).openConnection() : null;
        final BufferedInputStream JXAextensionStream = connection instanceof URLConnection ? new BufferedInputStream(connection.getInputStream()) : src instanceof BufferedInputStream ? (BufferedInputStream) src : src instanceof InputStream ? new BufferedInputStream((InputStream) src) : null;
(...)
while ((r = inputStream.read(b)) != -1) {
                        JXAtmpPath.write(b, 0, r);
                        rBytes += r;
                        if (progressBar) {
                            if (!(src instanceof File)) {
                                UIMessage.getProgressBar(id).setString("downloaded " + Math.rint(rBytes * 10 / 1024) / 10.0 + " Kbytes");
                            }
                            UIMessage.updateProgress(id, rBytes, (int) connection.getContentLength();
                        }
                        /*** ERASED, hangs the SYSTEM.OUT if (_debug) {
                        System.out.print(".");
                        }*/
                    }        

you can find this in JXAenvUtils._fileCopy() of sf3jswing-jxakernel below at sf.net. :smiley:

Woa! The worst code I’ve seen. Ever.

There’s no particular reason I’m using the class loader - other than that it works and caches in the way I want it to. Just has this problem with the progress bar.

I have not used the URLConnection before, but I will definitely give that a shot. I am concerned however that the caching it would use sounds like it is not as persistent as the JAR caching. (for example, it mentions circumventing the cache if the user hits refresh on their browser) With Jar Caching, the file is cached until the user manually deletes it or it is updated server-side.

Jesse

Then put every big resource in its own JAR.

It seems you do not have a signed application, so you can’t use custom ClassLoaders to monitor progress.

Yes that’s what I’m currently debating. It seems like that will work fine. But it makes me cry on the inside