Android:使用MuPdf開源庫閱讀PDF檔案
一時興起
因為自己前段時間一直在做故事會的一個客戶端,當然是非官方版,主要是由於自己的興趣所致。以前就挺喜歡看故事會的,所以就希望做一個故事會的客戶端,在手機上隨時隨地地看。因為故事會的官方APP的體驗實在是太差了,而且資源還不全(而且還收費),所以我就打算自己做一個,然後去收集網上的資源。因為網上的故事會是以PDF檔案的形式出現的,剛開始我想呼叫手機上的軟體例如WPS等來閱讀,後來一想反正做那就做PDF檔案閱讀功能吧,反正也沒做過,正好試試唄。
一波三折
說做就做,剛開始使用的開源庫是PDFView,就結果來說,軟體體積太大了,而且使用的時候載入有點慢了,所以當時就不是太想使用這個庫。後來沒辦法妥協唄,想了一個折中的辦法,在開始的時候,利用PDFView提供的方法將PDF檔案轉換成一張張的圖片儲存到手機裡,等載入的時候直接使用Picasso等載入圖片的庫來載入本地圖片,這樣總體來說還是不錯的,直接載入圖片比直接解析PDF檔案要快很多,所以就出現了第一個版本,有興趣的可以下載看一看。
後來,又隨便在網上搜了搜,又找到一個不錯的開源庫,也就是MuPdf,這個和PDFView相比體積小,只有原來的一半,這已經是一個很大的誘惑了,沒什麼比體積小更讓人扛不住的了。然後就開始找一些實現程式碼,最後找到了一個Eclipse版本的,它的閱讀方式是橫屏滑動閱讀,我更喜歡豎屏閱讀,所以就改成用ListView來顯示,而且重要的是可以直接去顯示,而不需要生成圖片在手機裡(因為這個做了實現封裝),所以我就改了改,然後使用LruCache來保證不會出現記憶體溢位的情況,Demo執行還是不錯的。
因為我的那個故事會客戶端是使用AndroidStudio開發的,所以必須把MuPdf移植到AndroidStudio上。因為MuPdf需要呼叫so檔案,所以我就先做了一個Demo,看看能不能執行出來,結果沒問題再移植,然後悲催就開始了!!
本來so接觸的就不多(其實很少%>_<%),所以怎麼匯入就是一個大問題,去網上搜有的說是建立jniLibs資料夾,然後放在裡面,然而並無卵用;還有的說將so檔案壓縮成jar檔案,然後放在libs裡面,同樣無卵用,最後真是要崩潰了。折騰了一下午,出去吃個晚飯,路上又搜了一種解決方法,告訴自己回去再試最後一次,不行我就放棄了,吃完飯回來試一下居然可以了,終於不在停止運行了。
問題出在哪我想暫時是找不到了,大概就是因為執行是沒有正確的載入so檔案,所以一些底層方法不能呼叫而崩潰了。
解決方法
task nativeLibsToJar(type: Zip, description: "create a jar archive of the native libs" ){
destinationDir file("$projectDir/libs")
baseName "Native_Libs2"
extension "jar"
from fileTree(dir: "libs", include: "**/*.so")
into "lib"
}
tasks.withType(JavaCompile){
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
將這一段程式碼加在build.gradle裡,同時將libmupdf.so檔案放在如下位置:
圖中的Native_Libs2.jar是編譯之後出現的,如果編譯之後沒有出現這個檔案,那麼可能就不會執行成功了。
哦,對了還要注意的是MuPdf的那些類的包名必須是com.artifex.mupdf,如下:
不然好像也不能執行成功。
柳暗花明
因為在AndroidStudio上可以執行成功了,所以我就打算將原來的客戶端重新改寫一下,將PdfViewer替換成MuPdf,一來可以減小APK的體積,二來也不用將PDF檔案轉換成圖片來顯示,很方便,等完成之後再將軟體上傳上來讓有興趣的看看。
下載
附:經朋友測試,發現如果開啟的PDF檔案如果是損壞的話,那麼應用就直接崩潰了,其次如果快速的關閉和開啟應用,那麼應用也會崩潰。這裡我上傳一份解決上述問題的版本(AndroidStudio版),它解決了上述問題,其實也就是換了一個so庫,不過確實不會崩潰就是了。還需要注意的是新版的載入so庫的方法和舊版不一樣,大家在build.gradle中可以看到。
因為我現在提供的so庫只有armeabi-v7a版本的,像是x86,armeabi等架構下的都沒有,在其他的手機上都出現了不能執行的問題。所以痛定思痛,我決定學習一下原始碼編譯,得到其他架構下的so檔案,還好不是太難,主要就是配置一下環境,具體內容可以參見我的這篇部落格《Android:ubuntu下編譯MuPDF原始碼》。