三方库 之 分分钟集成腾讯 TBS X5 。。。

LZ-Says:想和你喝酒是假,想醉你怀里是真。

前言

最近一段时间,都是在被前端虐了,还好,谈不上游刃有余,至少可以实现所需功能,调试起来也不会太过于懵逼。

当然,和大佬相比,还是差距很多。前段时间,因为个人原因,暂时停滞了前行之路,而今,慢慢拾起,希望努力实现自己想要的。

好久没碰 Android,今天拿 TBS X5 作为练手~

TBS X5 了解

曾经,在 Android 的世界里,加载网页,WebView 首当其冲,但是,当理想遇到显示,又出现如下情况 (节选自 TBS X5 官方)

  • 传统系统内核 ( Webview ) 存在适配成本高、不安全、不稳定、耗流量、速度慢、视频播放差、文件能力差等问题

那么针对以上提出的问题,我们该怎么办呢?

  • 优化?Enmmm,Sorry,打扰了。

  • 第三方开源方案,Enmmm,似乎还是有些问题,应用率以及使用率相对来说有待期待。

  • TBS X5?试试?

那么 TBS X5 是个什么鬼?它又是拥有着何样的才能呢?一起来看~

腾讯浏览服务(TBS,Tencent Browsing Service)整合腾讯底层浏览技术和腾讯平台资源及能力,提供整体浏览服务解决方案。

而 ta 又具有何方风采呢?为了省事儿,直接官方盗图~

  1. 速度快:相比系统 webview 的网页打开速度有 30+% 的提升;

  2. 省流量:使用云端优化技术使流量节省 20+%;

  3. 更安全:安全问题可以在 24 小时内修复;

  4. 更稳定:经过亿级用户的使用考验,CRASH 率低于 0.15%;

  5. 兼容好:无系统内核的碎片化问题,更少的兼容性问题;

  6. 体验优:支持夜间模式、适屏排版、字体设置等浏览增强功能;

  7. 功能全:在 Html5、ES6 上有更完整支持;

  8. 更强大:集成强大的视频播放器,支持视频格式远多于系统 webview;

  9. 视频和文件格式的支持 x5 内核多于系统内核;

  10. 防劫持是 x5 内核的一大亮点

简单了解之后,我们开始准备玩转操作~

TBS X5 实践

TBS X5 SDK 下载地址:https://x5.tencent.com/tbs/sdk.html
在这里插入图片描述
针对官方提供 SDK,这里我们选择 Android SDK(完整版),最新的更新日期为:2019-02-13。

首先创建项目,将下载下来的 So 库文件以及 Jar 包倒入工程,如下所示:
在这里插入图片描述
设置支持的 CPU 架构以及开启 DataBinding 支持:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        ...
        // 支持 CPU 架构
        ndk {
            abiFilters "armeabi"
        }
        ...
    }
    ...
    dataBinding {
        enabled = true
    }
}

dependencies {
    ...
    implementation files('libs/tbs_sdk_thirdapp_v4.3.0.1020_43633_sharewithdownload_withoutGame_obfs_20190111_105200.jar')
}

定义常量工具类:

package com.tbs.tbsdemo.app

/**
 * @author: heliquan
 * @data: 2019/3/28
 * @desc: 生活不易 且行且珍惜
 */

/**
 * 传递状态标志
 */
const val S_STATE_CODE = "stateCode"

/**
 * 加载网页
 */
const val S_LOAD_URL = "loadUrl"

/**
 * 加载视频
 */
const val S_LOAD_VIDEO = "loadVideo"

/**
 * URL 地址
 */
const val U_URL = "https://heliquan.blog.csdn.net/"

/**
 * 在线视频地址
 */
const val U_VIDEO = "https://img-cdn-qiniu.dcloud.net.cn/uniapp/doc/uni-app20190127.mp4"

随后嘛,添加对应的权限:

<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.GET_TASKS"/>

<!-- 硬件加速对X5视频播放非常重要,建议开启 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> 

定义 BaseApplication,初始化 TBS X5:

package com.tbs.tbsdemo.app.base

import android.app.Application
import android.util.Log
import com.tencent.smtt.sdk.QbSdk

/**
 * @author: heliquan
 * @data: 2019/3/28
 * @desc:
 */
class BaseApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        initTencentX5()
    }

    private fun initTencentX5() {
        val cb = object : QbSdk.PreInitCallback {

            override fun onViewInitFinished(arg0: Boolean) {
                Log.e("HLQ_Struggle", "x5 内核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核:$arg0")
            }

            override fun onCoreInitFinished() {
                Log.e("HLQ_Struggle", "x5 内核初始化 onCoreInitFinished")
            }
        }
        QbSdk.initX5Environment(applicationContext, cb)
    }

}

当然,不要忘记在 AndroidManifest 中指明,如下:

<application
        android:name=".app.base.BaseApplication"
        ...
        android:usesCleartextTraffic="true"
        tools:ignore="GoogleAppIndexingWarning">
    ...
</application>

接下来,搭建一个类似下面的门户:
在这里插入图片描述
并在首页设置跳转,这里默认已经创建了 Web 加载页:

package com.tbs.tbsdemo

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import com.tbs.tbsdemo.app.S_LOAD_URL
import com.tbs.tbsdemo.app.S_LOAD_VIDEO
import com.tbs.tbsdemo.app.S_STATE_CODE

/**
 * @author HLQ_Struggle
 * @date 2019年3月24日
 * @desc
 */
class MainActivity : AppCompatActivity() {

    private val mSelfActivity = MainActivity@ this

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    /**
     * Activity 跳转
     * @param stateCode
     */
    private fun startActivity(stateCode: String) {
        var intent = Intent(mSelfActivity, X5WebActivity::class.java)
        intent.putExtra(S_STATE_CODE, stateCode)
        startActivity(intent)
    }

    fun loadUrl(view: View) {
        startActivity(S_LOAD_URL)
    }

    fun loadVideo(view: View) {
        startActivity(S_LOAD_VIDEO)
    }

}

而最后则是开始着手编写我们 Web 加载页,简单说下想法:

  1. Web 页根据上页传递标志符进行动态设置加载 URL;
  2. Web 页加载时,顶部需要有进度条;
  3. 剩下则是 Web 常规设置,例如 WebSettings 等。

哦可,首先着手编辑 Web 页的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
    <data>

    </data>
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context=".X5WebActivity">

        <ProgressBar
                android:id="@+id/progress_bar"
                android:layout_width="match_parent"
                style="?android:attr/progressBarStyleHorizontal"
                android:indeterminateDrawable="@color/colorBar"
                android:progress="0"
                android:max="100"
                android:layout_height="3dp"/>

        <com.tencent.smtt.sdk.WebView
                android:id="@+id/x5_web"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

    </LinearLayout>

</layout>

下面,则是我们的 Web 加载页,很 easy,直接附上源码吧~

package com.tbs.tbsdemo

import android.databinding.DataBindingUtil
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.KeyEvent
import android.view.View
import android.widget.Toast
import com.tbs.tbsdemo.app.*
import com.tbs.tbsdemo.databinding.ActivityX5WebBinding
import com.tencent.smtt.export.external.interfaces.SslError
import com.tencent.smtt.export.external.interfaces.SslErrorHandler
import com.tencent.smtt.sdk.WebChromeClient
import com.tencent.smtt.sdk.WebSettings
import com.tencent.smtt.sdk.WebView
import com.tencent.smtt.sdk.WebViewClient

/**
 * @author HLQ_Struggle
 * @date 2019年3月24日
 * @desc 重新感受下 Android 之美 重新领略 Kotlin 优雅
 * */
class X5WebActivity : AppCompatActivity() {

    private val mSelfActivity = X5WebActivity@ this

    var mDataBind: ActivityX5WebBinding? = null

    var mLoadUrl = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        window.setFormat(PixelFormat.TRANSLUCENT)
        super.onCreate(savedInstanceState)
        mDataBind = DataBindingUtil.setContentView(mSelfActivity, R.layout.activity_x5_web)

        initLoadUrl()

        initX5WebViewSettings()
    }

    private fun initLoadUrl() {
        var stateCode = intent.getStringExtra(S_STATE_CODE)
        when (stateCode) {
            S_LOAD_URL -> {
                mLoadUrl = U_URL
            }
            S_LOAD_VIDEO -> {
                mLoadUrl = U_VIDEO
            }
            else -> {
                Toast.makeText(mSelfActivity, "传了个鸟啊这是???", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun initX5WebViewSettings() {
        // 支持获取手势焦点
        mDataBind?.x5Web?.requestFocusFromTouch()

        initWebSettings()

        initChromeClient()

        mDataBind?.x5Web?.loadUrl(mLoadUrl)
    }

    private fun initWebSettings() {
        val webSetting = mDataBind?.x5Web?.settings
        // 开启 JS
        webSetting?.javaScriptEnabled = true
        // 开启支持插件
        webSetting?.pluginsEnabled = true
        // 将图片调整适合 WebView 大小(响应式)
        webSetting?.useWideViewPort = true
        // 缩放至屏幕大小
        webSetting?.loadWithOverviewMode = true
        // 支持缩放
        webSetting?.setSupportZoom(true)
        webSetting?.builtInZoomControls = true
        // 隐藏默认缩放控件
        webSetting?.displayZoomControls = false
        // 支持重新布局
        webSetting?.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
        // 开启多窗口
        webSetting?.supportMultipleWindows()
        // 不使用缓存
        webSetting?.cacheMode = WebSettings.LOAD_NO_CACHE
        // 允许访问文件
        webSetting?.allowFileAccess
        // 允许通过 JS 打开新窗口
        webSetting?.javaScriptCanOpenWindowsAutomatically
        // 允许自动加载图片
        webSetting?.loadsImagesAutomatically = true
        // 允许定位
        webSetting?.setGeolocationEnabled(true)
        // 设置默认编码格式
        webSetting?.defaultTextEncodingName = "UTF-8"

        // 不显示水平滚动条
        mDataBind?.x5Web?.isHorizontalScrollBarEnabled = false
        // 不显示垂直滚动条
        mDataBind?.x5Web?.isVerticalScrollBarEnabled = false
    }

    private fun initChromeClient() {
        // 使用内置浏览器打开
        mDataBind?.x5Web?.webViewClient = object : WebViewClient() {

            /**
             * 开始加载网页
             */
            override fun onPageStarted(webView: WebView?, url: String?, bitmap: Bitmap?) {
                super.onPageStarted(webView, url, bitmap)
            }

            /**
             * 网页加载完成
             */
            override fun onPageFinished(webView: WebView?, url: String?) {
                super.onPageFinished(webView, url)
            }

            /**
             * 网页加载失败处理
             */
            override fun onReceivedError(webView: WebView?, errorCode: Int, desc: String?, faileUrl: String?) {
                super.onReceivedError(webView, errorCode, desc, faileUrl)
            }

            override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                view.loadUrl(url)
                return true
            }

            /**
             * Https 处理
             */
            override fun onReceivedSslError(webView: WebView?, handler: SslErrorHandler?, sslError: SslError?) {
                // 信任所有网址证书
                handler!!.proceed()
            }

        }
        mDataBind?.x5Web?.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                mDataBind?.progressBar?.progress = newProgress
                if (newProgress == 100) {
                    // newProgress 代表网页加载进度,到达 100 完成加载
                    mDataBind?.progressBar?.visibility = View.GONE
                }
            }
        }
    }

    /**
     * 重写返回 使其在网页中点击返回键可以依次返回上级
     */
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK && mDataBind?.x5Web?.canGoBack()!!) {
            mDataBind?.x5Web?.goBack()
        } else {
            finish()
        }
        return false
    }
}

一起来看效果演示图:
在这里插入图片描述
有的小伙伴说了,如何确保集成 TBS X5 成功呢?

很 easy,随便打开网页,复制显示小水滴即说明成功,如下所示:
在这里插入图片描述

后记

当然,TBS X5 也存在一些问题,例如不支持在线浏览 PDF 文件、不支持 64 位,不过暂时还没有遇到其他的。

iOS 提供的 WebView 相比 Android 可谓良心发现呐,简直爽的一批~

好了,简单回顾下 Android 以及 Kotlin,果不其然,好多忘记了,尴尬 😅😅😅

这里顿时想到鸡大大黑黑大脸又要说还是不熟悉,😅😅😅

好吧,好吧,我也要认认真真啦~

朝着鸡大大,冲鸭~

经历 Error

Q 1:net::ERR_CLEARTEXT_NOT_PERMITTED

如下图所示:
在这里插入图片描述
解决方案:

Mainifest 中的 application 添加如下:

android:usesCleartextTraffic="true"

参考地址:

https://stackoverflow.com/questions/52707918/webview-showing-err-cleartext-not-permitted-although-site-is-https

个人公众号

不定期发布博文,最近有点忙,感谢老铁理解,欢迎关注~

参考资料

  1. TBS X5 官方地址:https://x5.tencent.com/tbs/index.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章