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

时间:2012-01-12 00:13:43

标签: android android-ndk shared-libraries

我已将Assimp库构建为共享库。我把它包含在我的Android ndk项目中并且它构建正常但是当我加载它时我收到以下错误: 无法加载本机库:My-Native-Activity。

(也许我应该补充一点,当我没有包含库并且我检查了apk和设备时,我的活动正常工作;库被添加到libs文件夹并安装在/ data /中的设备上数据/我的应用内/ lib中。)

我已经做了很多阅读,似乎解决这个问题的唯一方法是在启动我的本机活动之前使用System.loadLibrary加载它们。我认为在采用这种方法之前,我更愿意使用dlopen动态加载它们。

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

我会将它构建为一个静态库,但它超过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)

4 个答案:

答案 0 :(得分:19)

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

package com.you;

public class MyNativeActivity extends android.app.NativeActivity {

    static {
       System.loadLibrary("assimp");
    }
 }

然后更改您的AndroidManifest.xml。将android.app.NativeActivity替换为MyNativeActivity,然后移除标记hasCode="false"

作为旁注,Android在加载共享库时会搜索依赖项。但搜索范围仅限于/system/lib

答案 1 :(得分:6)

您希望使用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);
    }
}

答案 2 :(得分:1)

使用System.loadLibrary是可行的方法。

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

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

此代码通常位于包含本机Java方法的类中(即使用关键字native定义的方法,这些方法映射到本机代码)。因为此代码在static块中执行,所以当Java类加载器加载类时(即在类中的任何代码实际执行之前)执行它。

您不必向assimp添加对LOCAL_LDLIBS的任何引用,因为您已经通过assimp声明引用了LOCAL_SHARED_LIBRARIES

This question可能相关。

答案 3 :(得分:0)

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

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

希望以上信息对你有用。