2012-01-12 81 views
15

我已經將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

回答

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

+1 hasCode =「false」刪除。我無法弄清楚爲什麼它不構建我的java代碼:P – 2012-10-31 19:39:04

+0

我猜你不會碰巧知道是否有任何方法可以完成此操作,而無需像package com那樣明確引用包名稱你;'在開始的路線?我問,因爲在APK文件中強制更改軟件包名稱時,代碼當然失敗。 Java noob在這裏。 – 2015-09-09 01:56:35

0

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

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,因爲你已經通過LOCAL_SHARED_LIBRARIES聲明引用assimp

This question可能是相關的。

+0

除非您繼承NativeActivity類(它不能成爲主要方法),否則靜態塊方法將無法工作,那麼在運行時應該有另一種方式來加載所需的所有庫,我認爲? – alexleutgoeb 2012-02-21 14:54:54

+0

你的照片讓我頭暈 – 2013-07-11 13:22:06

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

這很棒,適合我。一個nit:行'package com.example.native_activity;'在代碼框外,我錯過了它。原來這很關鍵。它會在沒有它的情況下進行編譯,但是我花了一個小時追趕班級爲什麼不加載!我試圖編輯,但除非我改變了至少六個字符,否則它不會讓我。 : - | – 2016-03-13 06:18:05