mike.adc mike.adc - 6 months ago 14
Android Question

How can I make android delete old native libraries?

I'm trying to delete some native libraries from my application because I don't use them anymore, but after I install the apk in my phone I can see that the native libraries are still there.
As I've seen, android does copy/update native libraries correctly just by replacing the file in my libs/ directory, but apparently it doesn't delete them when they're not in the apk anymore.
How do I know the libraries are still there? Well first of all the application's size remains the same and I'm deleting some really big libraries, and second, if I leave the System.load(...) statement the app is still able to load the library.

The only solution that I've found for this has been to uninstall the app and make a fresh install, but that's not an obvious solution for a user updating the app from google play, and yes this problem affects severely my app functionality.

I've checked and apparently I can delete the files by my self, say during a service creation, but I don't want to mess with the installation this way.

Do you know if there's a way to tell Android that it needs to delete all the native libraries and copy them again?

Thanks,
Mike

[EDIT]

I've just found that GB updates the libraries correctly, it deletes the now-missing as it should, but neither ICS nor JB do, those two leave the old .so files even when they're not in the apk anymore.

I tried deleting the .so files manually from /data/data/mypackage/lib but it won't let me.

Any ideas?

Answer

Ok, so I gave up on android to do this and I had to do it myself. I took some tips from here: http://www.moodstocks.com/2012/03/20/ice-cream-sandwich-why-native-code-support-sucks/.

Here's what I did:

  1. Make three zip files with the contents of the folders libs/armeabi, libs/armeabi-v7a and libs/x86 and named them libs_armeabi.zip, libs_armeabi_v7a.zip and libs_x86.zip respecively.

  2. Move the zip files to the res/raw folder.

  3. Delete the files under the three libs folders and re-create them with touch (in a -nix system), remember that ICS and JB don't delete the old files in the lib folder, so just deleting the files would cause the app to keep those files which are quite large.

  4. Verify the processor architecture programmatically with these two methods:

    public static boolean isArmv7() {
        try {
            return Build.VERSION.SDK_INT >= 4 && Build.class.getField("CPU_ABI").get(null).toString().startsWith("armeabi-v7");
        } catch (Throwable e) {}
    
        return false;
    }
    
    public static boolean isX86() {
        try {
            return Build.VERSION.SDK_INT >= 4 && Build.class.getField("CPU_ABI").get(null).toString().startsWith("x86");
        } catch (Throwable e) {}
    
        return false;
    }
    
  5. Depending on the processor architecture unzip one of the three files programmatically to any folder you want, I'm using /data/data/myPackage/app_libs (using context.getDir("libs",Context.MODE_PRIVATE); returns that path).

Probably there would be more logic involved here, something like extracting the libs_armeabi.zip file, and then extract the files from either libs_armeabi_v7a.zip or libs_x86.zip or none of them, overwriting the files that have the same name (I'm just wandering here because I haven't actually tried that), fortunately for me my libs on the three files were already renamed and are exclusive on each zip file, so I just need to extract one of the three files.

  1. Replace the System.loadLibrary method calls to System.load which supports loading the libraries using its full path, and add the full path for each library.

This method comes with added benefits:

  • As the libraries are zipped the apk size will be reduced, making the application in the google play store smaller.

  • Being the libraries stored inside the raw resources android won't copy them automatically, allowing you to copy them wherever you want and load them using a full path.

  • You can decide to copy the libraries to the sd card if you want, I wouldn't recommend that but now you're able to do it, for example when the phone doesn't have enough space.

Hope this helps!

Comments