1. 程式人生 > >Fresco引起的在arm64位機器上找不到對應的so庫

Fresco引起的在arm64位機器上找不到對應的so庫

背景

今天公司專案的應用,測試人員提了個bug,應用在檢視pdf文件時崩潰了,看了下崩潰日誌。

java.lang.UnsatisfiedLinkError: dlopen failed: "libs/armeabi-v7a/libmupdf.so" is 32-bit instead of 64-bit

libmupdf.so就是mupdf編譯來的so庫,意思是說該so是32位的,需要使用64位替代。確實,之前專案一直使用的是32位的,但是也有用64位的機器測過(紅米note3),之前遇到的是部分手機不能載入so檔案,couldn’t find *.so 這篇文章提到的問題,也解決了,能正常使用了。但,今天同一臺機子,卻不能使用了,想想,在這兩個版本的迭代過程中,引入的庫也就只有Fresco了,經過排查,問題真就出在這了。

問題

lib專案

這是最新應用的lib下的目錄結構,然後同樣打舊版本包的lib目錄,發現,舊的包只有armeabi-v7a這個資料夾,再檢視各個資料夾下的檔案,又發現,新版本的包中確實只有在armeabi-v7a資料夾下有libmupdf.so檔案,其他資料夾下的都是fresco的so檔案,而armeabi-v7a存放的是32位的so檔案。

問題原因

64位機器預設去查詢是否存在arm64-v8a目錄,如果存在,就會使用(載入)該目錄下合適的64位庫,如果沒有則回去lib下查詢32位的庫,而fresco的draw-pipeline太完善了考慮了64位的機器所以他的arm64-v8a下有so庫,對應的系統就建立了lib 64的檔案,而不再去找32位的庫。但是,我們的專案中只有armeabi-v7a 32位庫,以至於機器在查詢到arm64-v8a目錄下載入不到libmupdf.so庫,然後就崩潰了。

解決方案

解決的辦法當然是,讓機器如何載入到我們的so檔案了,那麼有如下幾種方案:

  1. 編譯其他CPU型號對應的so檔案
    如果按fresco適配的型號,那麼我們要重新編譯其他arm64-v8a、armeabi、x86、x86_64等4個型號的so檔案,我們專案中只有mupdf這個有原始碼,還有其他so檔案是沒有原始碼的,再者,如果要編譯的專案多,那麼是多麼耗時的一件事,所以,目前來看這個方案不是最佳的。

  2. 改變fresco的引用方式
    目前fresco的引用方式,是使用gradle的新增庫依賴的方式
    compile ‘com.facebook.fresco:fresco:0.9.0’
    那麼,如果要解決上面的問題,就要改變引用的方式:
    去掉gradle的依賴,將fresco原始碼clone下來自行編譯,然後將armeabi-v7a目錄下的so檔案拷貝到專案的lib/armeabi-v7a資料夾下,接著拷貝如下幾個module的aar檔案
    這裡寫圖片描述


    最後,就是Android Studio引入aar。關於怎麼引入,可以自行查閱資料,或者有需要的話,我會在另外寫一個。
    最後,你發現這種方法動的地方很多,還是很麻煩,有沒有更簡單的?接著看第三種方案。

  3. 修改gradle配置(究極方案)
    可以說這個方案是最完美的解決方法了,簡單一本萬利!
    fresco的引用還是使用gradle的compile來新增依賴,只是開啟專案的build.gradle然後新增如下配置:
android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a'
        }
    }
}

ndk的abiFilters屬性,填寫的是需要的CPU型號,比如我只要arm32位的,所以只填寫了armeabi-v7a。ok,完美解決!