Android 抛弃原生WebView,使用腾讯X5内核、并加入广告拦截。 - Go语言中文社区

Android 抛弃原生WebView,使用腾讯X5内核、并加入广告拦截。


大家都不知道原生的WebView 存在各种坑。各种适配问题。

最近在使用,总会出现DNS被拦截的情况。预览了各个大神的论坛与博客。

发现可以更改WebView内核。找到了比较火的两个。

 

分别是:腾讯X5内核 和 crosswalk  

     crosswalk : 据说很强大,但缺点就是会让你的APK包增大很多。(我还没试过,都是看大神们的博客说的)

     大家可以参考这篇文章 如何轻松搞定Crosswalk之嵌入模式

    相对crosswalk呢,腾讯X5 比较适合我目前的项目。至少包不会一下子给我 增大那么多  

     TBS腾讯浏览服务(点击跳转官网)

 

    

 

  腾讯X5的好处我就不再说了,官网解释的肯定比我到位,我怎么做的吧。

 

第一步:那肯定是下载官方的SDK 包啦(腾讯浏览服务-SDK下载) 我这里下载的是上面这个

 

第二步:根据SDK 提供的jar包和so 包拷贝到自己的项目下。

    (注意:我这里和官方提供的so,放的位置可能有点区别,这个就需要看的项目情况了)

    

注意:x5暂时不提供64位so文件,为了保证64位手机能正常加载x5内核,请参照如下链接修改相关配置

https://x5.tencent.com/tbs/technical.html#/detail/sdk/1/34cf1488-7dc2-41ca-a77f-0014112bcab7

 

官方的Demo ,so包是放在 srcmainjniLibs  下这个可以看一下官方包。就知道了

在Demo 中的build.gradle,中有说到 so 包的目录位置

 

 

第三步:接下来就开始被配置,初始化X5了,在APP的 ApplicationonCreate()  去初始化

 

    private void initX5() {
        QbSdk.setDownloadWithoutWifi(true);
        //x5内核初始化接口//搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
        QbSdk.initX5Environment(getApplicationContext(),  new QbSdk.PreInitCallback() {
            @Override
            public void onViewInitFinished(boolean arg0) {
                //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
                Log.d("app", " onViewInitFinished is " + arg0);
            }
            @Override
            public void onCoreInitFinished() {
            }
        });
    }

在清单文件中去添加

        <!-- 腾讯X5内核初始化 -->
        <service android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
            android:label="dexopt"
            android:process=":dexopt" />

 

第四步 :继承  com.tencent.smtt.sdk.WebView  自定义 WebView (这里根据自己的情况定义)

 

public class SimpleWebView extends com.tencent.smtt.sdk.WebView {

    public SimpleWebView(Context context) {
        super(context);
        init();
    }

    public SimpleWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SimpleWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void init() {
		
		WebSettings webSetting = this.getSettings();
        webSetting.setJavaScriptEnabled(true);
        webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
        webSetting.setAllowFileAccess(true);
        webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setBuiltInZoomControls(true);
        webSetting.setUseWideViewPort(true);
        webSetting.setSupportMultipleWindows(true);
        // webSetting.setLoadWithOverviewMode(true);
        webSetting.setAppCacheEnabled(true);
        // webSetting.setDatabaseEnabled(true);
        webSetting.setDomStorageEnabled(true);
        webSetting.setGeolocationEnabled(true);
        webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
        // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
        webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
        // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
        webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);

        this.setWebViewClient(new SimpleWebViewClient());

        this.setWebChromeClient(new WebChromeClient(){
            //这里可以设置进度条。但我是用另外一种
            @Override
            public void onProgressChanged(WebView webView, int i) {
                super.onProgressChanged(webView, i);
            }
        });
    }

    public static class SimpleWebViewClient extends com.tencent.smtt.sdk.WebViewClient {

        private SimpleLoadingDialog loadingDialog;

        @Override
        public com.tencent.smtt.export.external.interfaces.WebResourceResponse shouldInterceptRequest(com.tencent.smtt.sdk.WebView webView, String url) {
            //做广告拦截,ADFIlterTool 为广告拦截工具类
            if (!ADFilterTool.hasAd(webView.getContext(),url)){
                return super.shouldInterceptRequest(webView, url);
            }else {
                return new WebResourceResponse(null,null,null);
            }
        }
        /**
         * 防止加载网页时调起系统浏览器
         */
        @Override
        public boolean shouldOverrideUrlLoading(com.tencent.smtt.sdk.WebView webView, String url) {
            webView.loadUrl(url);
            return true;
        }
        //在开始的时候,开始loadingDialog
        @Override
        public void onPageStarted(com.tencent.smtt.sdk.WebView webView, String s, Bitmap bitmap) {
            super.onPageStarted(webView, s, bitmap);
            try{
                loadingDialog = new SimpleLoadingDialog(webView.getContext(),true);
                loadingDialog.show();
            }catch (Exception e){}
        }
        //在页面加载结束的时候,关闭LoadingDialog
        @Override
        public void onPageFinished(com.tencent.smtt.sdk.WebView webView, String s) {
            super.onPageFinished(webView, s);
            try {
                if (loadingDialog != null) {
                    loadingDialog.dismiss();
                }
            } catch (Exception e) {}
        }

        @Override
        public void onReceivedError(com.tencent.smtt.sdk.WebView webView, com.tencent.smtt.export.external.interfaces.WebResourceRequest webResourceRequest, com.tencent.smtt.export.external.interfaces.WebResourceError webResourceError) {
            super.onReceivedError(webView, webResourceRequest, webResourceError);
        }

        @Override
        public void onReceivedSslError(com.tencent.smtt.sdk.WebView webView, com.tencent.smtt.export.external.interfaces.SslErrorHandler sslErrorHandler, com.tencent.smtt.export.external.interfaces.SslError sslError) {
            sslErrorHandler.proceed();
        }

    }
}

 

 

 

接下来就是使用了,和我们原生的webView 没什么区别啦。

 

    /**
     * 初始化webView
     */
    @SuppressLint("SetJavaScriptEnabled")
    private void initDetailsH5() {
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new SimpleWebView.SimpleWebViewClient(){

            @Override
            public void onPageFinished(com.tencent.smtt.sdk.WebView webView, String url) {
                super.onPageFinished(webView, url);
                toolbarTitle.setText(webView.getTitle());//获取WebView 的标题,设置到toolbar中去
            }

            @Override
            public boolean shouldOverrideUrlLoading(com.tencent.smtt.sdk.WebView webView, String url) {
                if (url.contains("Activity/")){
                    ...

                }else if (url.contains("Share")){
                    ...
                }else {
                    webView.loadUrl(url);
                }
                return true;
            }

        });
    }

 

    /**
     * 监听系统返回键,判断WebView是否有上一级,有的话就返回WebView的上一级
     * 否则返回页面
     *
     * @param keyCode
     * @param event
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (webView != null && webView.canGoBack()) {
                webView.goBack();
                return true;
            } else {
                return super.onKeyDown(keyCode, event);
            }
        }
        return super.onKeyDown(keyCode, event);
    }

 

 

 

第五步:这里也根据需要添加吧。就是广告拦截了。广告库加多了的话,可能就会影响性能了。

            (我觉的这种做法存在很大的问题,如果建议直接使用Https。就可以避免这个问题)

public class ADFilterTool {

    /**
     * 屏蔽广告的NoAdWebViewClient类
     *
     * @param context
     * @param url
     * @return true 为广告链接,false 为正常连接
     */
    public static boolean hasAd(Context context, String url) {
        Resources res = context.getResources();
        String[] adUrls = res.getStringArray(R.array.adBlockUrl);
        for (String adUrl : adUrls) {
            if (url.contains(adUrl)) {
                return true;
            }
        }
        return false;
    }
}

 

在 res vlaues 目录下创建 AdUrlString.xml

 

 

(注:广告库部分摘取 Android Webview广告过滤的实现

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="adBlockUrl">
        <item>ubmcmm.baidustatic.com</item>
        <item>gss1.bdstatic.com/</item>
        <item>cpro2.baidustatic.com</item>
        <item>cpro.baidustatic.com</item>
        <item>lianmeng.360.cn</item>
        <item>nsclick.baidu.com</item>
        <item>caclick.baidu.com/</item>
        <item>jieaogd.com</item>
        <item>publish-pic-cpu.baidu.com/</item>
        <item>cpro.baidustatic.com/</item>
        <item>hao61.net/</item>
        <item>cpu.baidu.com/</item>
        <item>pos.baidu.com</item>
        <item>cbjs.baidu.com</item>
        <item>cpro.baidu.com</item>
        <item>images.sohu.com/cs/jsfile/js/c.js</item>
        <item>union.sogou.com/</item>
        <item>sogou.com/</item>
        <item>5txs.cn/</item>
        <item>liuzhi520.com/</item>
        <item>yhzm.cc/</item>
        <item>jieaogd.com</item>
        <item>a.baidu.com</item>
        <item>c.baidu.com</item>
        <item>mlnbike.com</item>
        <item>alipays://platformapi</item>
        <item>alipay.com/</item>
        <item>jieaogd.com</item>
        <item>vipshop.com</item>
    </string-array>
</resources>

 

接下来就是  CookieUtils  ,同步WebView 的Cookie。为什么要同步Cookie ,我这就不介绍啦。

可以看一下我另外一篇文章,会有比较详细的Cookie同步。Android H5 交互Cookie 同步登录状态

 

 

最后温馨提醒一下,如果没有添加权限,注意加一下权限噢~

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

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

 

第六步:如果需要做适配兼容的需要配置以下配置

兼容视频播放:

1)享受页面视频的完整播放体验需要做如下声明:

页面的Activity需要声明 android:configChanges="orientation|screenSize|keyboardHidden"

2)视频为了避免闪屏和透明问题,需要如下设置

a)网页中的视频,上屏幕的时候,可能出现闪烁的情况,需要如下设置:Activity在onCreate时需要设置:

getWindow().setFormat(PixelFormat.TRANSLUCENT);//(这个对宿主没什么影响,建议声明)

b)在非硬绘手机和声明需要controller的网页上,视频切换全屏和全屏切换回页面内会出现视频窗口透明问题,需要如下设置

声明当前<item name="android:windowIsTranslucent">false</item>为不透明。

特别说明:这个视各app情况所需,不强制需求,如果声明了,对体验更有利

c)以下接口禁止(直接或反射)调用,避免视频画面无法显示:

webview.setLayerType()

webview.setDrawingCacheEnabled(true);

 

第七步:输入法设置

避免输入法界面弹出后遮挡输入光标的问题

方法一:在AndroidManifest.xml中设置

android:windowSoftInputMode="stateHidden|adjustResize"

方法二:在代码中动态设置:

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

 

还有一些其他的配置信息 我这里就不在搬官方的介绍了。

混淆配置、APP自定义UA、Tbs视频播放器接入...等等。官方描述还是很清晰的

 

好啦,到这里就全部介绍完啦。希望对你帮助。

 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_35070105/article/details/80047595
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 03:57:54
  • 阅读 ( 2187 )
  • 分类:职场

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢