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

问题描述:

我已经将Assimp库构建为共享库。我已经将它包含在我的Android ndk项目中,并且构建正常,但是当我加载它时,出现以下错误: 无法加载本机库:My-Native-Activity。从Android本地活动加载第三方共享库

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

我已经做了很多的阅读,看来解决这个问题的唯一方法是在启动我的本地活动之前使用System.loadLibrary加载它们。我想我更喜欢在采取这种方法之前使用dlopen动态加载它们。

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

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

这是我的Android.mk: 我试过在LOCAL_LDLIBS中添加-lassimp。我不确定这是否正确,但没有任何区别。

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) 
+0

我正在解决这个问题。我可以看到我的共享.so库出现在数据文件夹中。然而,android_main永远不会被调用,如果我编译链接共享它的主库只是不会加载。 – Halsafar 2012-06-05 23:07:11

+0

你有没有得到assimp在Android上工作?你可以把一些示例代码放在github上吗?我无法从资产目录加载。 Assimp允许实现你自己的IOSystem和IOStream,但是我无法实现它!事务处理! – 2013-06-07 09:11:22

子类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

+1 hasCode =“false”删除。我无法弄清楚为什么它不构建我的java代码:P – 2012-10-31 19:39:04

+0

我猜你不会碰巧知道是否有任何方法可以完成此操作,而无需像package com那样明确引用包名称你;'在开始的路线?我问,因为在APK文件中强制更改软件包名称时,代码当然失败。 Java noob在这里。 – 2015-09-09 01:56:35

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

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

希望以上信息对你有用。

+0

感谢您的建议。我不知道他们为什么去那个文件夹,但他们被封装到一个apk文件中,作为ndk-build的一部分,通过eclipse(我在apk文件中检查了libs目录)。然后使用adb(再次通过eclipse)安装apk,这就是他们结束的地方。我用adb shell来找到它们,我会进一步调查。 – 2012-01-12 10:40:49

+0

啊,导航到/ data/data/my-app /并做了一个ls -al。 libs文件夹中有一个到/ mnt/asec/my-app/lib的符号链接。 我会更新主帖以反映这一点。再次感谢。 – 2012-01-12 10:49:06

使用System.loadLibrary是要走的路。

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

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

此代码通常会在其中包含本地Java方法(即用关键字native定义的方法,它通过为本地代码映射)类。由于此代码在static块中执行,因此它在Java类加载器加载类时执行 - 即在类中的任何代码实际执行之前执行。

你不应该有任何引用assimp添加到LOCAL_LDLIBS,因为你已经通过LOCAL_SHARED_LIBRARIES声明引用assimp

This question可能是相关的。

+0

除非您继承NativeActivity类(它不能成为主要方法),否则静态块方法将无法工作,那么在运行时应该有另一种方式来加载所需的所有库,我认为? – alexleutgoeb 2012-02-21 14:54:54

+0

你的照片让我头晕 – 2013-07-11 13:22:06

您想通过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); 
    } 
} 
+0

这很棒,适合我。一个nit:行'package com.example.native_activity;'在代码框外,我错过了它。原来这很关键。它会在没有它的情况下进行编译,但是我花了一个小时追赶班级为什么不加载!我试图编辑,但除非我改变了至少六个字符,否则它不会让我。 : - | – 2016-03-13 06:18:05