去年有兩篇文章在介紹怎麼支援將網頁輸出成 epub 檔案,分別說明了怎樣處理網頁的文字內容,和儲存圖片的方式。
這一次要介紹的是:既然 EinkBro 都可以儲存 epub 檔案了,那要不要順便也支援一下閱讀 epub 檔案呢?(反正 epublib 函式庫有支援相關功能)如果能利用 EinkBro 閱讀 epub 檔案的話,那要不要也再支援一下內容的註記功能呢?
開發自己的專案的好處是,不會有人跟你說 NO。只要你想做,有時間做,知道怎麼做,什麼都是可能的。
雖然說我試著讓 EinkBro 支援閱讀 epub 檔案,但功能其實相當的陽春和不完整。唯一能確保的是,如果是利用 EinkBro 儲存下來的 epub 檔案,應該都可以被順利開啟。開啟後,EinkBro 支援的各項功能就都可以用在 epub 檔案上 (更換字型,點擊畫面翻頁,全文翻譯等等)。
話說,雖然 epublib 有支援,但網路上的例子真是少得可憐。找到最完整,能夠參考的例子在這兒。這個範例雖然能動,但它完全沒有遵照 Java 的 Coding Convention:所有的函式、變數名稱都是大寫的。所以,需要一些 refactoring effort 才能拿來用。
它會先繼承 WebView
建立 EpubReaderView
,然後利用 epublib 從檔案中讀出內容,將內容寫到 local file storage 等著後續的操作。主要有下面三個步驟:
OpenEpubFile()
要可以開啟 epub 檔案的話,首先要處理的是 TOC (Table of Contents):從裡面拿出各 Chapter 的 html,建立成列表。在這個步驟中,會建立 logcal folder path,以便用來儲存該章節裡需要被呈現的圖片 (438行)
DownloadResource()
從 epub 中過濾出所有圖片資源,並將它們一一寫入 local storage。
GotoPosition()
做完步驟1,2 後,所有的資料都已經準備好了;這時我們可以呼叫 WebView
的 loadDatawithBaseURL()
,base 設為 ResourceLocation
。這麼一來,WebView 就可以正常地讀取到存在 local storgae 的圖片檔案。
再來它會呼叫 GotoPosition()
來跳到使用者想要的位置。如果在程式中有先記住使用者最後閱讀的位置的話,這函式可以用來跳到該章節和位置。
上述的步驟一二三雖然可行,但不是很優雅。epub 只是一個單一檔案,為了閱讀它,必須在本地端建立暫存目錄,寫入多個暫存檔案;這都需要額外的 I/O 處理。如果你有開發過 WebView 相關功能的話,應該都知道其實可以攔截 WebResourceRequest,做客製化的操作。就讓我解釋怎麼改寫上面的作法吧。
在 NinjaWebViewClient
,需要改寫 shouldInterceptRequest()
來支援 epub 中的圖片需求。215 行會檢查 url scheme:看是不是 EinkBro 生成的 epub 中使用的 img scheme。這方式無法適用於一般的 epub 文件;但對於 EinkBro 產生的 epub 檔案是夠用的,不用再將圖片資訊寫到 local storage。
這麼一來,我們就可以利用 EinkBro 閱讀它自己建立的 epub 檔案了。下一篇會再解釋怎麼在開啟中的 epub 文件中註記被選擇的文字區塊,並且會有示範的影片喔。
EinkBro 中完整的 EpubReaderView.kt