从Android本机活动加载第三方共享库

我已经将Assimp库构build为共享库。 我已经把它包含在我的Android ndk项目,它build立良好,但是当我加载它,我得到以下错误:无法加载本机库:我的本地活动。

(也许我应该补充说,当库不包含在内时,我的活动工作正常,并且已经检查了apk和设备上;库被添加到libs文件夹并安装在设备上的/ data / data / my -app / lib中。)

我已经做了大量的阅读,似乎解决这个问题的唯一方法是在启动我的本地活动之前使用System.loadLibrary加载它们。 我想我更喜欢在使用dlopen之前dynamic加载它们。

我正确的假设Android不会自动加载共享库我的本地活动(即我的共享库)依赖?

我会build立它作为一个静态库,但它已经超过54Mb,这将无法正常工作。

这是我的Android.mk:我已经尝试将-lassimp添加到LOCAL_LDLIBS。 我不确定这是否正确,但没有任何区别。

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := assimp LOCAL_SRC_FILES := libassimp.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := native-activity LOCAL_SRC_FILES := main.cpp LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 LOCAL_STATIC_LIBRARIES := android_native_app_glue LOCAL_SHARED_LIBRARIES := assimp LOCAL_CPPFLAGS += -march=armv7-a -mfloat-abi=softfp LOCAL_CFLAGS := $(LOCAL_CPPFLAGS) TARGET_ARCH_ABI := armeabi-v7a LOCAL_C_INCLUDES += $(LOCAL_PATH) include $(BUILD_SHARED_LIBRARY) $(call import-module,android/native_app_glue) 

Solutions Collecting From Web of "从Android本机活动加载第三方共享库"

子类android.app.NativeActivity是解决这个问题最简单的方法。

 package com.you; public class MyNativeActivity extends android.app.NativeActivity { static { System.loadLibrary("assimp"); } } 

然后改变你的AndroidManifest.xml 。 用MyNativeActivityreplaceandroid.app.NativeActivity并移除标签hasCode="false"

作为一个侧面说明,Android在加载共享库时会search依赖关系。 但search范围仅限于/system/lib

您想用Java活动启动NativeActivity。 这样,您可以在NativeActivity之前加载共享库。

AndroidManifest.xml

 <application android:label="@string/app_name" android:hasCode="true"> <activity android:name="DummyActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="android.app.NativeActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden"> <meta-data android:name="android.app.lib_name" android:value="native-activity" /> </activity> </application> 

DummyActivity.java

 package com.example.native_activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class DummyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { System.loadLibrary("some_shared_lib"); System.loadLibrary("native-activity"); super.onCreate(savedInstanceState); Intent intent = new Intent(DummyActivity.this, android.app.NativeActivity.class); DummyActivity.this.startActivity(intent); } } 

使用System.loadLibrary是要走的路。

Android不会自动为您加载相关的共享库。 所以你需要做这样的事情:

 static { System.loadLibrary("assimp"); // dependency .so first System.loadLibrary("native-activity"); // dependent .so second } 

这个代码通常在包含本地Java方法的类(即用关键字native定义的方法,映射到本地代码)中进行。 因为这个代码是在一个static块中执行的,所以当Java类加载器加载这个类时,即在类中的任何代码被执行之前,这个代码就会被执行。

您不应该添加任何引用assimpLOCAL_LDLIBS因为您已经通过LOCAL_SHARED_LIBRARIES声明引用了assimp

这个问题可能是相关的。

1:U不能使用dlopen,因为System.loadLibrary是从Java层加载本地库的唯一方法。 2:Ur库path看起来不正确,位置应该是/ data / data / urapp / lib /

你需要将你的库文件压缩到你的apk文件中,在安装的时候,android会将它解压缩并自动放到/ data / data / urapp / lib /。

希望以上信息对你有用。