Question

My app is very image-heavy, so I need to supply expansion files with my APK. I've chosen to store all my images in a ZIP file and use the zip library to get access to my images.

My first intuition was to unzip all files when the app is first started and store them in the app's external directory. The guide gently nudges me to take a different approach:

Reading media files from a ZIP

If you're using your expansion files to store media files, a ZIP file still allows you to use Android media playback calls that provide offset and length controls (such as MediaPlayer.setDataSource() and SoundPool.load()). In order for this to work, you must not perform additional compression on the media files when creating the ZIP packages.

So I guess I'll just get an input stream from the zip file when I have to, but I don't really know how long I should have that zip file open.

Suppose I have a gallery activity with a ViewPager that shows one image per page. Do I open my expansion zip file in onCreate and close it in onDestroy, or do I open and close the file for every new image loaded?

Was it helpful?

Solution

From API level 9, you could use the jobb tool to package your assets and use StorageManager to mount/dismount the OBB file. You can also use this tool to encrypt the assets, if need be.

OBBs are a good way of providing large amounts of binary assets without packaging them into APKs as they may be multiple gigabytes in size. However, due to their size, they're most likely stored in a shared storage pool accessible from all programs.

...

The OBB will remain mounted for as long as the StorageManager reference is held by the application. As soon as this reference is lost, the OBBs in use will be unmounted. The OnObbStateChangeListener registered with this call will receive the success or failure of this operation.

I guess a mounted OBB file can dismount at any unexpected time (for example, when the user turns on USB mass storage), so pay extra attention to your OnObbStateChangeListener.

Example from this question:

storage = (StorageManager) getSystemService( STORAGE_SERVICE );
storage.mountObb( obbFilepath, "optional_encryption_key", myListener );

You can use obbContentPath to read files just like they would be on disk.

private final OnObbStateChangeListener myListener = new OnObbStateChangeListener() {
    @Override
    public void onObbStateChange(String path, int state) {
        super.onObbStateChange(path, state);
        d(path + " changed to state " + state);
        switch (state) {
            case ERROR_ALREADY_MOUNTED:
            case ERROR_COULD_NOT_MOUNT:
            case ERROR_COULD_NOT_UNMOUNT:
            case ERROR_INTERNAL:
            case ERROR_NOT_MOUNTED:
            case ERROR_PERMISSION_DENIED:
            case UNMOUNTED:
                //TODO
                break;
            case MOUNTED:
                String assetsPath = mStorageManager.getMountedObbPath(mPathToObb);
                if (assetsPath == null) throw new NullPointerException("Could not get path to mounted OBB path");
                d("Checking if " + assetsPath + "/path/to/file exists");
                File f = new File(assetsPath + "/path/to/file");
                d("" + f.exists());                    
                break;
            default:
                break;
        }
    }
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top