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?
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
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).
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