2016-05-16 35 views
1

我有一個使用一些JNI代碼的Android應用程序。長話短說(雙關語意),幾乎不可能將JNI庫轉換爲64位,因爲它需要很多改變。代碼(Java和JNI)在armeabi-v7a體系結構上很好地工作。在Android上強制CPU/ABI到armeabi-v7a

這些庫正在使用loadLibrary加載。當我嘗試在Nexus 6上運行我的應用時,該應用加載正常。一旦loadLibrary被執行,應用程序就會崩潰,描述的錯誤爲here

這個問題,據我瞭解,在Nexus 6上執行時,應用程序會建立爲arm64-8a。但是這些庫不是爲arm64-8a構建的(因爲64位版本在問題開始時提到了問題)。

我的問題是,我可以強制arm64-8a設備也運行armeabi-v7a代碼?如何強制我的應用程序apk成爲armeabi-v7a,因此無論設備如何,它只有32位?

回答

5

是的,arm64-v8a設備也可以運行armeabi-v7a代碼。

安裝APK時,安裝程​​序會檢查包是否包含官方目錄中的庫,並根據結果將活動標記爲32或64位。

如果它在APK中找到lib/arm64-v8a中的庫(通常從​​構建目錄中的目錄libs/arm64-v8a中獲取),它將被標記爲64位,並且將忽略所有其他目錄。如果它在APK中找到lib/armeabi-v7alib/armeabi中的庫,則該進程將標記爲32位。如果其中沒有任何本地庫,安裝程序會假定應用程序根本不使用本機代碼,並且可以在任何模式下自由運行,實際上可以在64位模式下運行。

現在,如果您在64位模式下發送了一些但不是全部的庫,該進程將以64位模式啓動,並且將無法加載32位庫(甚至不會安裝)。在這種情況下,除非所有這些庫都可用,否則必須避免捆綁任何64位庫。

或者你不使用官方的libs目錄,但以其他方式安裝你的庫(例如,通過在運行時下載它們或將它們保存在例如資產中),系統不知道你的進程想運行32 bit模式(此時切換到另一個模式爲時已晚)。在這些情況下,請確保以正常/官方方式至少包含一些虛擬庫,以便將應用程序標記爲32位。

請參閱https://stackoverflow.com/a/33919454/3115956https://stackoverflow.com/a/27713998/3115956https://stackoverflow.com/a/35450911/3115956以獲得類似問題的答案。

+0

感謝您的回答。我認爲複雜性會阻礙你在第二段中描述的內容 - 我定義了外部依賴關係(特別是領域和亞馬遜AWS),他們似乎正在下載arm64-v8a。我將我的JNI庫改爲.a文件,但不知道如何正確加載它。我能否強迫我的圖書館在加載之前等有機會影響ABI選擇?依賴關係在app build.gradle中定義,例如'compile'c​​om.amazonaws:aws-android-sdk-s3:2.2.11'' – LNI

+0

加載的庫的實際順序無關緊要;重要的是APK中存在不同的ABI目錄。如果你的一個依賴項包含'arm64-v8a',那麼這個目錄將會在APK中結束,APK安裝程序將選擇這個體系結構。嘗試查看您的構建APK('unzip -l filename.apk')並查看它包含的架構目錄。但是,您可以做的是過濾掉實際包含哪些ABI;嘗試在您的gradle文件中添加'abiFilters'armeabi-v7a'',以使其僅包含這種單一架構。 – mstorsjo

+0

我將您的答案標記爲正確,因爲我可以驗證在另一個64位庫不存在時應用程序默認爲32位。在我的情況下,問題是由realm-android引起的 - 我在應用程序和項目build.gradle文件中都有條目來啓用領域插件。這迫使arm64-v8a庫被加載。我會嘗試abiFilters步驟並修改此評論。 – LNI