views:

848

answers:

3

I am developing a library for Android that requires frequent updates from a central server. I was thinking how nice it would be if my library could update itself -- or if I could just release a bootstrap library that downloads the target library when the app is installed.

I see this class in 1.5 called "DexClassLoader" but there seems to be precious little on the web besides the API docs. Has anyone used this successfully for the scenario which I described?

Also, do the terms of the Android Market permit such a thing?

+1  A: 

Indeed what you want is supported and works. DexClassLoader is not working as expected for me, but the following code works fine.

DexFile df = new DexFile(new File("/data/app/my_downloaded_lib.apk"));
ClassLoader cl = getClassLoader();
Class clazz = df.loadClass("com/my/lib/MyClass", cl);

About the market question, i don't see any issue with this, but you have to read the EULA to be sure.

Lucas S.
This works, but making a File object is counterproductive: DexFile will take the path and open it itself. You could use the constructor that takes a String path.
Chris Boyle
Hello, maybe you are right, but when i answered, this was the only way it works.
Lucas S.
+1  A: 

I've successfully used DexClassLoader. It's important to provide a dexOutputDir that is actually writeable by your app, so not /data/dalvik-cache. Otherwise the log will show one or two lines about failing to write there, followed by ClassNotFoundException.

cl = new DexClassLoader("/full/path/com.example.apk",
                        getFilesDir().getAbsolutePath(),// /data/data/foo/files
                        null,  // native lib path, I haven't used this
                        MyClass.class.getClassLoader());
// This doesn't make Class.forName() work, instead I do this:
Class<?> foo = cl.loadClass("com.example.foo");

To make Class.forName() work, you could try Thread.setContextClassLoader() (I haven't).

Chris Boyle
+1  A: 

DexClassLoader is the right answer. Applications should never use DexFile directly (it's meant to be used by class loaders).

You can use /sdcard (get the path via Environment.getExternalStorageDirectory(), requires the WRITE_EXTERNAL_STORAGE permission), or the app's private data area, for the "dexOutputDir" parameter. External storage is usually larger, but if the card is ejected your app will be killed. The app-private data area also has the advantage of being cleaned up automatically if the app is uninstalled.

fadden
I would also think that loading code off the SD card would be somewhat insecure.
CommonsWare