最近在NDK開發中遇到了一個奇怪的問題,希望記錄下,可以幫到大家:
我編譯了一些 .so 動態庫,只編譯了armeabi-v7a、armeabi 指令集,其它指令集編譯不了,具體原因還沒查出。因為同時也調用了第三方的.so 動態庫,而第三方提供7個指令集,分別為:arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64。 所以,我只能把剛編譯的動態庫填充到 armeabi、armeabi-v7a 兩個指令集目錄。
在JNI 調用的時候,有些手機調用成功,有些手機不行,成功的有:
(vivo Y51A) Android 系統為:5.1 ,支持指令集:armeabi-v7a、armeabi
(oppo r9s) Android 系統為:5.1 ,支持指令集:arm64-v8a、armeabi-v7a、armeabi
(魅族 note2) Android 系統為:5.1 ,支持指令集:arm64-v8a、armeabi-v7a、armeabi
不成功的手機:
(華為 榮耀6) Android 系統為:7.0 ,支持指令集:arm64-v8a、armeabi-v7a、armeabi
(華為 mate9) Android 系統為:7.0 ,支持指令集:arm64-v8a、armeabi-v7a、armeabi
你可以通過 以下代碼獲取你手機支持的指令集:
String[] abis = new String[]{}; abis = Build.SUPPORTED_ABIS;
一般64位芯片的手機都會兼容 32位的庫,只是運行時性能慢一點。如華為 mate9 的芯片就是 64位的,它首先會 查詢 字符數組 abis 支持指令集 的第一個元素:arm64-v8a,如果這個目錄沒有相應的 庫,就會到第二個元素目錄搜索, 以此類推。
我不確定是因為華為手機的問題, 還是 Android 7.0 系統的問題:當你在 jniLibs 目錄下建立了 arm64-v8a,程序就會直接在 arm64-v8a 目錄下查找,如果查找不到,就會直接報錯,而不會去其它 指令集目錄查找,錯誤提示為:
nativeLibraryDirectories=[/data/app/com.lukouapp-1/lib/arm64, /vendor/lib64, /system
而上面列舉成功的三款手機就會主動搜索 其它指令集目錄下的庫。這令我很疑惑,那我就嘗試把
除 armeabi-v7a、armeabi 目錄外的其它目錄都刪了,然后運行。 還是不行,各種嘗試,都沒有成功,后面我在 stackoverflow 找到一個解決方案,鏈接如下:
按照stackoverflow 的解決方案是:
找到apk 安裝文件,然后用rar 之類的解壓工具打開:

lib 目錄,就是編譯后的靜態或者動態庫目錄,然后再進去看看:

果然, lib 目錄下 除 armeabi-v7a、armeabi 目錄外,還有其它目錄,我在 JniLibs目錄下 刪除了其它目錄,根本沒有起到作用,我覺得原因可能是之前 build 時候緩存了 這些目錄,所以不管我怎么在 jniLibs 目錄下刪除其它指令集目錄都沒用。 你可以嘗試在 Android Studio 的菜單 Build =》 clean Project,然后再運行項目。
其次也可以 在 build.gradle 文件下 添加如下配置:
android { splits { abi { enable true reset() include 'armeabi-v7a', 'armeabi' } } }
該配置是 讓再構建build的時候只 加入armeabi-v7a', 'armeabi' 兩種指令集。最后,大功告成,以上手機都運行通過。目前大多數第三方庫 都已經提供 arm64-v8a 指令集, 所以最佳方案還是盡量去編譯 arm64-v8a 指令集。
tips:華為手機在系統方面走得比較前,更新迭代快,對權限以及其它方面都比較多特殊的限制,對我們開發者來說是一種嘗試,也是一種挑戰,希望開發者不要忽視了它,畢竟它在大陸市場用戶率不低。