无法加载本地共享库的依赖在本土活动的应用程序 [英] Can't load native shared library with dependencies in a native activity app
问题描述
在我的Android应用我有4个库:
libTemplate.so
取决于libPorkholt.so
libPorkholt.so
取决于libpng15.so
取决于liblua.so
取决于libopenal.so
libpng15.so
liblua.so
libopenal.so
如果我写了一个小的命令行可执行文件链接对libTemplate和手动调用ANativeActivity_onCreate,它链接和运行得很好(如果我点LD_LIBRARY_PATH以/data/data/com.mycompany.Template/lib)
如果我跑我的应用程序,我得到这个非常有用的错误消息:
E / AndroidRuntime(13214):java.lang.RuntimeException的:无法启动的活动ComponentInfo {com.mycompany.Template / android.app.NativeActivity}:java.lang.IllegalArgumentException异常:无法加载本地库:/data/data/com.mycompany.Template/lib/libTemplate.so
它甚至没有进入ANativeActivity_onCreate,所以我只能猜测是,就是它有事情做与联
我也许应该提到,我使用CMake的这个脚本: HTTP:// code.google.com/p/android-cmake/ 建库自己(不NDK建造)。我设法与它编译天然活性样品,所以我知道它的工作原理。
另外,我确信没有库包含在它的soname一个版本号
我的清单:
< XML版本=1.0编码=UTF-8&GT?;
<! - BEGIN_INCLUDE(清单) - >
<舱单的xmlns:机器人=http://schemas.android.com/apk/res/android
包=com.mycompany.Template
安卓版code =1
机器人:VERSIONNAME =1.0>
<! - 这是一个平台的API,其中NativeActivity的介绍。 - >
<使用-SDK安卓的minSdkVersion =9/>
<! - 这.apk文件有C本身没有Java $ C $,所以设置了code为false。 - >
<应用机器人:标签=模板Porkholt项目的Android版本:有code =假>
< - !我们的活动是内置NativeActivity的框架类。
这将需要与我们的NDK code积分的照顾。 - >
<活动机器人:名称=android.app.NativeActivity
机器人:标签=模板Porkholt工程
机器人:configChanges =方向| keyboardHidden>
&所述;! - 给NativeActivity的名称或的.so - >
<元数据的android:NAME =android.app.lib_name
机器人:值=模板/>
<意向滤光器>
<作用机器人:名称=android.intent.action.MAIN/>
<类机器人:名称=android.intent.category.LAUNCHER/>
&所述; /意图滤光器>
< /活性GT;
< /用途>
< /舱单>
<! - END_INCLUDE(清单) - >
由于显然Android是没有足够的智慧正确设置LD_LIBRARY_PATH,我设法通过创建一个小的引导程序库,手动加载实际活动来解决我的问题。这里的code:
的#include<安卓/ native_activity.h>
#包括<安卓/ log.h>
#包括< dlfcn.h中>
#包括< errno.h中>
#包括< stdlib.h中>
#定义LOGI(...)((无效)__ android_log_print(ANDROID_LOG_INFO,Porkholt,__VA_ARGS__))
#定义LOGE(...)((无效)__ android_log_print(ANDROID_LOG_ERROR,Porkholt,__VA_ARGS__))
#定义LIB_PATH/数据/数据/ @ PH_BUNDLE_ID @ / lib中/
void *的load_lib(为const char * 1)
{
void *的句柄=的dlopen(L,RTLD_NOW | RTLD_GLOBAL);
如果(!手柄)
{
LOGE(的dlopen(\%s \中):%S,L,字符串错误(错误));
出口(1);
}
返回的句柄;
}
无效ANativeActivity_onCreate(ANativeActivity *应用程序,无效* UD,为size_t udsize)
{
LOGI(加载自举);
load_lib(LIB_PATHlibpng15.so);
load_lib(LIB_PATHliblua.so);
load_lib(LIB_PATHlibopenal.so);
load_lib(LIB_PATHlibPorkholt.so);
无效(*主)(ANativeActivity *,无效*,为size_t)=的dlsym(load_lib(LIB_PATHLIB @ PH_APP_TARGET @。所以),ANativeActivity_onCreate);
如果(!主)
{
LOGE(未定义的符号ANativeActivity_onCreate);
出口(1);
}
主(应用程序,UD,udsize);
}
In my Android app I have 4 libraries:
libTemplate.so
depends on libPorkholt.so
libPorkholt.so
depends on libpng15.so
depends on liblua.so
depends on libopenal.so
libpng15.so
liblua.so
libopenal.so
If I write a small command line executable that links against libTemplate and manually call ANativeActivity_onCreate, it links and runs just fine (if I point LD_LIBRARY_PATH to /data/data/com.mycompany.Template/lib)
If I run my app I get this very useful error message:
E/AndroidRuntime(13214): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.Template/android.app.NativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/data/com.mycompany.Template/lib/libTemplate.so
It doesn't even enter ANativeActivity_onCreate, so my only guess is that's it has something to do with linking
I should probably mention that I'm using CMake with this script: http://code.google.com/p/android-cmake/ to build the libraries myself (without ndk-build). I managed to compile the native-activity sample with it, so I know it works.
Also, I made sure no library contains a version number in its soname
My manifest:
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mycompany.Template"
android:versionCode="1"
android:versionName="1.0">
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="9" />
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application android:label="Template Porkholt project" android:hasCode="false">
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name="android.app.NativeActivity"
android:label="Template Porkholt project"
android:configChanges="orientation|keyboardHidden">
<!-- Tell NativeActivity the name of or .so -->
<meta-data android:name="android.app.lib_name"
android:value="Template" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<!-- END_INCLUDE(manifest) -->
Since apparently Android isn't smart enough to set a LD_LIBRARY_PATH correctly, I managed to solve my problem by creating a small bootstrapper library that manually loads the actual activity. Here's the code:
#include <android/native_activity.h>
#include <android/log.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Porkholt", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "Porkholt", __VA_ARGS__))
#define LIB_PATH "/data/data/@PH_BUNDLE_ID@/lib/"
void * load_lib(const char * l)
{
void * handle = dlopen(l, RTLD_NOW | RTLD_GLOBAL);
if (!handle)
{
LOGE("dlopen(\"%s\"): %s", l, strerror(errno));
exit(1);
}
return handle;
}
void ANativeActivity_onCreate(ANativeActivity * app, void * ud, size_t udsize)
{
LOGI("Loaded boostrap");
load_lib(LIB_PATH "libpng15.so");
load_lib(LIB_PATH "liblua.so");
load_lib(LIB_PATH "libopenal.so");
load_lib(LIB_PATH "libPorkholt.so");
void (*main)(ANativeActivity*, void*, size_t) = dlsym(load_lib(LIB_PATH "lib@PH_APP_TARGET@.so"), "ANativeActivity_onCreate");
if (!main)
{
LOGE("undefined symbol ANativeActivity_onCreate");
exit(1);
}
main(app, ud, udsize);
}
这篇关于无法加载本地共享库的依赖在本土活动的应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!