zoukankan      html  css  js  c++  java
  • 记一次腾讯TBS浏览服务集成实践

    这次的分享源于最近的实际开发工作。

    项目需求是

    • 在原生Android应用中嵌入WebView,放置用于支撑音视频直播业务的Web页;

    • 另外还需提供Word、Excel、PowerPoint、PDF等常见文档格式的内容预览。

    经过一番技术选型,最终选定集成腾讯TBS浏览服务进项目,支撑如上所述两个功能。

    能力集成

    1. 首先进入下图所示网页,在该下载页下载SDK并保存。

    1. 下载成功后,将jar包放入要集成该能力的Module的libs目录下。随后,在Android Studio中以Project视图方式显示项目树形结构,找到这个jar包,单击右键,选择“Add as Library”。稍等片刻,即可完成库引入。

    2. 接着,打开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" />
    
    1. 初始化SDK,分别在Java代码和AndroidManifest.xml中执行以下代码初始化腾讯TBS:
    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了。在导包时,注意要导入以下包,而非系统原生:

    
    import com.tencent.smtt.sdk.WebSettings;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    

    载入网页并执行JS方法

    基本实现

    这一步比较简单,和使用系统原生WebView及相关API基本一致。我把要载入的网页放到了项目的assets目录下,因此我的这部分代码片段如下:

    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对象。

    除上述基本的加载网页外,我还希望在网页加载完成后调用里面的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安全连接错误

    在实际调试中,我发现只做完以上工作,网页并不能显示出来,原因是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);
    

    好了,到此,我们就完成了网页的内嵌以及常见文档的预览。

    本次分享到此就结束了,希望以上内容对你有所帮助。

  • 相关阅读:
    命令拷屏之网络工具
    PHP 设计模式 笔记与总结(1)命名空间 与 类的自动载入
    Java实现 计蒜客 1251 仙岛求药
    Java实现 计蒜客 1251 仙岛求药
    Java实现 计蒜客 1251 仙岛求药
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 蓝桥杯 算法训练 字符串合并
    Java实现 LeetCode 143 重排链表
    Java实现 LeetCode 143 重排链表
  • 原文地址:https://www.cnblogs.com/wenhanxiao/p/14060779.html
Copyright © 2011-2022 走看看