2014-09-03 76 views
9

我有一個應用程序2本地庫。 1st在ARMv7上運行得更快,所以我的版本都是針對ARMv7和ARMv5的。 2nd在兩個平臺上的工作方式都相同,因此只提供ARMv5庫。Android L預覽不搜索「armeabi」文件夾中的本地庫(UnsatisfiedLinkError)

我的本地庫文件夾是這樣的:

/jniLibs/ 
    | 
    +---armeabi/ 
    |  | 
    |  +---libFirstLibrary.so 
    |  +---libSecondLibrary.so 
    | 
    +---armeabi-v7a/ 
      | 
      +---libFirstLibrary.so 

的應用效果良好的所有設備和Android版本的生產。

當我與L-預覽(錘頭lpv79預覽-ac1d8a8e.tgz)測試了我的Nexus 5,我得到這個錯誤:

java.lang.UnsatisfiedLinkError: Couldn't load SecondLibrary from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.package-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.package-1, /vendor/lib, /system/lib]]]: findLibrary returned null 
    at java.lang.Runtime.loadLibrary(Runtime.java:358) 
    at java.lang.System.loadLibrary(System.java:610) 

的問題是,儘管Nexus 5的有CPU_ABI設置爲armeabi-v7aCPU_ABI2設置爲armeabi,L-Preview僅使用CPU_ABI值,並且僅在「armeabi-v7a」文件夾中查找「SecondLibrary」,並且因爲它不存在而崩潰。

當我將.so文件複製到「armeabi-v7a」文件夾時,一切正常,但是APK的大小是3.5 MB,我並不喜歡它。

這僅僅是Android L-Preview或一些「新功能」的bug嗎?

回答

5

據我所知,這一直是我們的預期行爲,而我很疑惑爲什麼這種方法對你有用。

鏈接器不會在每個loadLibrary調用中瀏覽完整的APK文件,而是在安裝APK時提取正確的本機庫。只使用一個單獨的體系結構目錄,因此如果它找到lib/armeabi-v7a,它甚至不會查找lib/armeabi。

在一些老版本的android(4.0.3和更早版本)中有一個已知的問題,armeabi可以被意外地用來代替armeabi-v7a,但不知道這是什麼讓它看起來適合你。

參見例如https://android.googlesource.com/platform/ndk/+/532389e89c/docs/text/CPU-ARCH-ABIS.text對此進行了正式解釋(第III部分「Android平臺上的ABI管理」,特別是第III.3小節和第III.1小節末尾的註釋)。

編輯︰它實際上似乎包管理器可以安裝一些文件從輔助ABI目錄,即使主要ABI目錄存在,在android版本到kitkat。 http://albin.abo.fi/~mstorsjo/hellojni-test-abis.zip是我的測試示例的源代碼,而http://albin.abo.fi/~mstorsjo/hellojni-test-abis.apk是它的二進制文件。此示例創建四個本機庫,libgello-jni.so,libhello-jni.so,libhello-jni2.solibtello-jni.so。這些文件是專門爲所有的ABI,但在armeabi-v7a,我已經取消了所有的文件,除了libhello-jni.so - 文件列表(針對ARM架構的目錄),因此看起來是這樣的:

lib/armeabi/libgello-jni.so 
lib/armeabi/libhello-jni.so 
lib/armeabi/libhello-jni2.so 
lib/armeabi/libtello-jni.so 
lib/armeabi-v7a/libhello-jni.so 

在安裝奇巧armeabi-v7a設備上,則從armeabi-v7a目錄安裝libhello-jni.so,從armeabi目錄安裝libhello-jni2.solibgello-jni.so - 但完全不安裝libtello-jni.so。安裝的文件似乎取決於APK中的名稱和順序。因此,根據您的文件名稱,您可能以前有過運氣,並且這已經奏效 - 即使文檔明確表示它不應起作用。在android-L預覽版中,這種不一致似乎已被糾正。

+0

一般來說,但幾乎所有設備都支持兩個ABI。就我而言,Nexus 5支持:'CPU_ABI = armeabi-v7a'和'CPU_ABI2 = armeabi'。對於主設備ABI爲「x86」但輔助爲「armeabi」的英特爾設備使用相同的機制,因此即使在「x86」文件夾中沒有本機庫,我的應用也可在英特爾設備上正常運行。在我看來,沒有理由說這種方法在L-Preview上不起作用。 – xsveda 2014-09-03 19:15:09

+1

是的,但是如果在主ABI目錄中沒有找到,則包管理器僅檢查輔助ABI目錄中的庫。我鏈接的文檔說:「包管理器服務將掃描.apk並查找任何共享庫的形式:lib//lib .so [...]如果找到一個,那麼它被複制到' $ APPDIR/lib/lib .so' [...]如果找不到,並且定義了輔助ABI,則該服務將掃描以下格式的共享庫:lib//lib 。所以」。所以如果主要的ABI目錄不是空的,它不會檢查次要的。 – mstorsjo 2014-09-03 19:30:28

+0

這就是我原來的答案 - 它只能從一個單一的體系結構目錄中提取 - 它可以是主要的或次要的ABI。 – mstorsjo 2014-09-03 19:36:55

相關問題