不同於iOS,Android的webView不支援開啟office和pdf文件,所以當我們遇到在應用內開啟office和pdf文件的需求時,往往無法從系統原生功能去支援。這篇文章的寫下筆者在Android應用中整合office和pdf檔案能力的心得,附上demo地址:github.com/windinwork/…
一、確定解決方案
Android應用開啟office和pdf檔案。常用的有以下四種解決方案:
- 線上網頁開啟檔案方案:通過微軟或谷歌提供的線上頁面開啟office和pdf檔案
- 整合相關文件處理開源庫:通過整合開源庫類似於AndroidPdfViewer
- 通過系統中的第三方應用開啟文件
- 整合騰訊x5 sdk檔案能力
四種方案各有優劣,這裡筆者選擇了x5 sdk為主要手段,第三方應用輔助的這樣一種解決方案
二、整合x5核心
騰訊官方提供的x5核心有兩個版本,這裡選擇具有檔案能和的sdk:
接下來的整合可以參考x5核心接入文件,這裡便不詳述。整合的主要工作便是整合jar包和so檔案,並在Application初始化時呼叫QbSdk.initX5Environment(context, callback)來完成初始化工作。
三、整合TbsReader
x5核心中提供了TbsReaderView,讓我們可以通過這個類在App中顯示文件。考慮到TbsReaderView這個類具有生命週期的方法,我們把它封裝在一個Fragment中,方便我們的呼叫。TbsReaderView的主要方法有兩個,一個是preOpen(String, boolean),另一個是openFile(Bundle)。preOpen(String, boolean)是用來檢測x5檔案能力是否成功初始化和是否支援開啟檔案的格式,當符合開啟檔案的條件時該方法返回true;openFile(Bundle)則是在preOpen(String, boolean)的返回值為true的情況進行呼叫,顧名思義這個方法是用來開啟檔案的,其中bundle用來傳入檔案路徑。
String path = file.getPath();
String format = parseFormat(path);
boolean preOpen = mReaderView.preOpen(format, false); // 該狀態標誌x5檔案能力是否成功初始化並支援開啟檔案的格式
if (preOpen) { // 使用x5核心開啟office檔案
Bundle bundle = new Bundle();
bundle.putString("filePath", path);
bundle.putString("tempPath", StorageUtils.getTempDir(context).getPath());
mReaderView.openFile(bundle);
}
複製程式碼
有了這部分核心程式碼,TbsReaderView基本上就能開啟Office和PDF檔案了。
四、完善檔案能力
市面上的安卓手機各式各樣,雖然整合了TbsReaderView,但是還是會收到使用者反饋說無法開啟Office檔案。這是因為使用者手機上的x5檔案能力沒有初始化成功,至於為什麼沒有初始化成功,原因還無法確定。針對這部分使用者,我們需要在他們無法使用TbsReaderView瀏覽Office檔案的情況下,提供另外的途徑去開啟Office檔案。大致思路是檢測到TbsReaderView無法開啟Office或PDF時,跳轉到第三方應用去開啟。這裡x5的jar包提供了這樣一個api:openFileReader(Context, String, HashMap<String, String>, ValueCallback)用來使用第三方應用開啟檔案,並且支援前往下載具有Office瀏覽功能的QQ瀏覽器,這樣的功能對使用者比較友好,我們可以直接拿來用。
然而,x5的jar包中使用第三方應用開啟時呼叫了Uri.fromFile(file),這個生成檔案Uri的方法在Android7.0以下有效,但在Android7.0及以上會造成崩潰,這是Android7.0的檔案許可權管理導致。為了使Android7.0及以上的使用者可以正常跳轉到第三方應用開啟,我們需要使用FileProvider去獲取Uri,但程式碼在Jar包中寫死了。幸運的是,經過多次嘗試,發現可以將跳轉到第三方應用開啟的這部分程式碼複製出來,修正Uri.fromFile(file)的程式碼以正常呼叫,免去了要修改jar的麻煩。這裡筆者把這部分程式碼封裝在一個叫TbsReaderAssist的類中,輔助呼叫。
這樣一來,一個比較完善的開啟Office和PDF的功能就算做完成。
String path = file.getPath();
String format = parseFormat(path);
boolean preOpen = mReaderView.preOpen(format, false); // 該狀態標誌x5檔案能力是否成功初始化並支援開啟檔案的格式
if (preOpen) { // 使用x5核心開啟office檔案
Bundle bundle = new Bundle();
bundle.putString("filePath", path);
bundle.putString("tempPath", StorageUtils.getTempDir(context).getPath());
mReaderView.openFile(bundle);
} else { // 開啟檔案失敗,可能是由於x5核心未成功初始化引起
if (QbSdk.isSuportOpenFile(format, 1)) { // 再次檢查檔案是否支援
HashMap<String, String> params = new HashMap<>();
params.put("style", "1");
params.put("local", "false");
TbsReaderAssist.openFileReader(context, path, params, null);
}
}
複製程式碼
五、總結
這裡筆者寫了一個App開啟Office或PDF檔案的解決方案,個人認為對於一個App來說是相對完善的處理。這裡是demo的地址:github.com/windinwork/…,共享出來,可以讓有需要做類似功能的小夥伴少走些彎路。