How do I import shared object libraries at runtime in Android?

强颜欢笑 提交于 2019-12-10 10:43:06

问题


I am developing an open-source emulator project, and it has multiple, customizable native plug-ins. These plug-ins are built as native shared object libraries (.so files), and have various interfaces between native and Java through JNI. Rather than distribute the APK with every single plug-in ever created, and in order to allow folks to build their own custom plug-ins, I need a method of importing these .so files any time after the app has been installed.

I've found that I can copy files to the folder /data/data/[package_name], but not to the lib/ sub-folder (because it is owned by the "system" group). To utilize the JNI interfaces in Java, I must call System.loadLibrary( libname ); However, this seems to require the .so file to be located in the lib/ sub-folder. The only way around this I can think of is to require the user to have a rooted device. Is there another way to accomplish this?


回答1:


Use System.load() instead:

static
{
    final String[] libs = {
        "/data/data/com.foo.test/lib/liba.so",
        "/data/data/com.foo.test/lib/libb.so"
    };

    for (int i=0; i<libs.length; ++i)
    {
        Log.d(TAG, "Loading " + libs[i] + "...");
        System.load(libs[i]);
    }
}

$ adb logcat

D/LibTest ( 1022): Loading /data/data/com.foo.test/lib/liba.so...
D/dalvikvm( 1022): Trying to load lib /data/data/com.foo.test/lib/liba.so 0x40512640
D/dalvikvm( 1022): Added shared lib /data/data/com.foo.test/lib/liba.so 0x40512640
D/dalvikvm( 1022): No JNI_OnLoad found in /data/data/com.foo.test/lib/liba.so 0x40512640, skipping init
D/LibTest ( 1022): Loading /data/data/com.foo.test/lib/libb.so...
D/dalvikvm( 1022): Trying to load lib /data/data/com.foo.test/lib/libb.so 0x40512640
D/dalvikvm( 1022): Added shared lib /data/data/com.foo.test/lib/libb.so 0x40512640
D/dalvikvm( 1022): No JNI_OnLoad found in /data/data/com.foo.test/lib/libb.so 0x40512640, skipping init




回答2:


Distribute your plugins as APKs, and communicate from the host to the plugins via IPC mechanisms:

  • broadcast Intents
  • services (command or binding patterns)
  • ContentProvider

As a side bonus, if a plugin needs more/different permissions than the host, this is supported.

Admittedly, this will require IPC, which adds non-trivial overhead, steering you in the direction of a coarse-grained plugin communication protocol. And, it will use up more RAM (and the extra CPU time for the overhead will use up more battery life).




回答3:


You can use dlopen for loading a so file with c++. I use this code in c++ to load so files in any folder.

// KGEmain function pointer
typedef void (*KGEmain) ();

std::string strPluginName = "/data/data/com.kge.android/lib/lib";
strPluginName += appname;
strPluginName += ".so";

void* handle = dlopen(strPluginName.c_str(), RTLD_LAZY);

const char* error;

if (!handle)
{
    LOGE("can't load the %s plugin. (%s)", strPluginName.c_str(), dlerror());
    return;
}
// Clear any exiting error
dlerror();

// Load the KGEmain function
pFn = (KGEmain)dlsym(handle, "KGEmain");
if ((error = dlerror()) != NULL || !pFn)
{
    LOGE("KGEmain function dose not find in %s plugin.\n%s", strPluginName.c_str(), error);
    return;
}

pFn();


来源:https://stackoverflow.com/questions/10324956/how-do-i-import-shared-object-libraries-at-runtime-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!