此次的分享源於最近的實際開發工做。javascript
項目需求是html
在原生Android應用中嵌入WebView,放置用於支撐音視頻直播業務的Web頁;java
另外還需提供Word、Excel、PowerPoint、PDF等常見文檔格式的內容預覽。android
通過一番技術選型,最終選定集成騰訊TBS瀏覽服務進項目,支撐如上所述兩個功能。web
下載成功後,將jar包放入要集成該能力的Module的libs目錄下。隨後,在Android Studio中以Project視圖方式顯示項目樹形結構,找到這個jar包,單擊右鍵,選擇「Add as Library」。稍等片刻,便可完成庫引入。安全
接着,打開Android原生項目的AndroidManifest.xml配置文件,聲明以下權限(特別注意須要申請動態權限的權限,應另外作申請):網絡
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.front" />
HashMap map = new HashMap(); map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true); map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true); QbSdk.initTbsSettings(map);
<service android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService" android:label="dexopt" android:process=":dexopt"> </service>
到此,咱們就能夠和使用系統原生WebView API同樣去使用騰訊TBS中的WebView了。在導包時,注意要導入如下包,而非系統原生:app
import com.tencent.smtt.sdk.WebSettings; import com.tencent.smtt.sdk.WebView; import com.tencent.smtt.sdk.WebViewClient;
這一步比較簡單,和使用系統原生WebView及相關API基本一致。我把要載入的網頁放到了項目的assets目錄下,所以個人這部分代碼片斷以下:ide
WebSettings webSettings = videoPreviewWv.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(true); webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); webSettings.setDisplayZoomControls(false); webSettings.setAllowFileAccess(true); webSettings.setDomStorageEnabled(true); webSettings.setDatabaseEnabled(true); webSettings.setAppCacheEnabled(true); videoPreviewWv.loadUrl(Environment.VIDEO_RECORD_URL);
注:videoPreviewWv爲WebView對象。ui
除上述基本的加載網頁外,我還但願在網頁加載完成後調用裏面的js方法,以便在網頁加載完成後馬上開始直播。
所以,我增長了以下方法:
videoPreviewWv.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView webView, String s) { super.onPageFinished(webView, s); String jsStr = "javascript:open('" + SharedPrefUtil.getToken(activity) + "', '" + Environment.VIDEO_IP + "', " + Integer.parseInt(sn) + ", '" + Environment.VIDEO_STUN_IP + "'" + ")"; videoPreviewWv.evaluateJavascript(jsStr, null); } });
當網頁加載完畢後,onPageFinished()方法被回調。
evaluateJavascript()則負責調用js方法,各位能夠按照jsStr字符串的值做爲格式參考,適配本身的js文件。
如上代碼所示,當網頁加載完畢後,我調用了js中的open()方法,傳入了token、視頻推流IP等參數。
對於無需任何參數的js方法,我以中止直播的方法爲例:
videoPreviewWv.evaluateJavascript("javascript:close()", null);
怎麼樣?還算簡單吧?不過,到此,網頁仍是顯示不正常。
通過反覆排查,我發現問題在於如下三點:
在實際調試中,我發現只作完以上工做,網頁並不能顯示出來,緣由是SSL安全鏈接錯誤。
當遇到這種問題時,咱們但願忽略並繼續加載網頁。實現起來也很容易:
videoPreviewWv.setWebViewClient(new com.tencent.smtt.sdk.WebViewClient() { @Override public void onReceivedSslError(WebView webView, com.tencent.smtt.export.external.interfaces.SslErrorHandler sslErrorHandler, com.tencent.smtt.export.external.interfaces.SslError sslError) { sslErrorHandler.proceed(); } });
到此,網頁能夠顯示了。可是,依然存在不足。
每次執行js的open()方法時,因爲網頁會請求攝像頭和麥克風的權限,依然會有權限請求的對話框,而實際上用戶已經在以前,被原生代碼請求過權限需求了。這樣一來,至關於重複請求權限。並且每次開啓直播,都會請求一次。
那麼,有沒有辦法讓嵌入的WebView默認容許這些權限呢?
固然有,下面是自動給予權限的相關代碼:
videoPreviewWv.setWebChromeClientExtension(new IX5WebChromeClientExtension() { @Override public boolean onPermissionRequest(String s, long l, MediaAccessPermissionsCallback mediaAccessPermissionsCallback) { long allowed = 0; allowed = allowed | MediaAccessPermissionsCallback.ALLOW_AUDIO_CAPTURE; mediaAccessPermissionsCallback.invoke(s, allowed, true); return true; } }
通過上述一系列操做,咱們想要的功能已經實現了。不過還有最後一點美中不足——網頁有白邊。
這個問題其實不是原生代碼的問題,須要修改嵌入的Web頁面(HTML)。加上以下代碼:
<style> body{ margin:0px } </style>
好了,到此,WebView的嵌入就完成了。
接下來,咱們再來聊聊使用騰訊TBS進行常見類型文檔的預覽。
因爲文檔預覽暫時不支持在線文件,所以須要咱們先把文件下載到本地。網絡下載不是本文的重點,這裏就再也不詳述了。
不過,若是咱們須要成功使用騰訊TBS的文件預覽能力,須要在AndroidManifest.xml中作以下聲明:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provide_file_paths" /> </provider>
其中,provide_file_paths內容以下:
<?xml version="1.0" encoding="utf-8"?> <resources> <paths> <external-path name="sdcard" path="" /> <files-path name="my_files" path="cache" /> </paths> </resources>
關於provide_file_paths的定義規則,另請搜索:」FileProvider 路徑配置策略」。
文件下載成功後,執行下列代碼打開文件預覽界面。
HashMap<String, String> params = new HashMap<String, String>(); params.put("local", "true"); params.put("style", "1"); JSONObject Object = new JSONObject(); try { Object.put("pkgName", activity.getApplicationContext().getPackageName()); } catch (JSONException e) { e.printStackTrace(); } params.put("menuData", Object.toString()); QbSdk.openFileReader(activity, file.getAbsolutePath(), params, null);
好了,到此,咱們就完成了網頁的內嵌以及常見文檔的預覽。
本次分享到此就結束了,但願以上內容對你有所幫助。