• 【前期准备】 腾讯X5 jar包下载地址 [点击打开] 本次完整DEMO源码 [打开Github] 【集成步骤】 第一步:下载jar包添加到项目 ..."android.permission.WRITE_EXTERNAL_STORAGE" />  "and


    前期准备

    腾讯X5 jar包下载地址 [点击打开]

    本次完整DEMO源码 [打开Github]

    【集成步骤】

    第一步:下载jar包添加到项目

    第二步:添加权限

    [java] view plain copy
    1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
    3. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
    4. <uses-permission android:name="android.permission.INTERNET" />  
    5. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  

    第三步:创建BaseApplication.class

    [java] view plain copy
    1. import android.app.Application;  
    2. import com.tencent.smtt.sdk.QbSdk;  
    3. import com.tencent.smtt.sdk.TbsListener;  
    4. import com.xiong.tbs_x5.utils.LogUtil;  
    5.   
    6. /** 
    7.  * Created by xiongwenwei@aliyun.com 
    8.  * CreateTime: 2017/1/12 
    9.  * Note:BaseApplication 
    10.  */  
    11. public class BaseApplication extends Application {  
    12.   
    13.     private static BaseApplication instance;  
    14.   
    15.     @Override  
    16.     public void onCreate() {  
    17.         super.onCreate();  
    18.   
    19.         instance = this;  
    20.         initTbs();  
    21.     }  
    22.   
    23.     private void initTbs() {  
    24.         //搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。  
    25.         QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {  
    26.   
    27.             @Override  
    28.             public void onViewInitFinished(boolean arg0) {  
    29.                 LogUtil.i("onViewInitFinished is " + arg0);  
    30.             }  
    31.   
    32.             @Override  
    33.             public void onCoreInitFinished() {  
    34.             }  
    35.         };  
    36.   
    37.         QbSdk.setTbsListener(new TbsListener() {  
    38.             @Override  
    39.             public void onDownloadFinish(int i) {  
    40.                 LogUtil.i("onDownloadFinish");  
    41.             }  
    42.   
    43.             @Override  
    44.             public void onInstallFinish(int i) {  
    45.                 LogUtil.i("onInstallFinish");  
    46.             }  
    47.   
    48.             @Override  
    49.             public void onDownloadProgress(int i) {  
    50.                 LogUtil.i("onDownloadProgress:" + i);  
    51.             }  
    52.         });  
    53.   
    54.         QbSdk.initX5Environment(getApplicationContext(), cb);  
    55.     }  
    56.   
    57.     public static BaseApplication getInstance() {  
    58.         return instance;  
    59.     }  
    60. }  
    不要忘记添加:


    第三步:创建tbs_activity.xml

    [java] view plain copy
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:orientation="vertical">  
    6.   
    7.     <com.tencent.smtt.sdk.WebView  
    8.         android:id="@+id/webView"  
    9.         android:layout_width="match_parent"  
    10.         android:layout_height="match_parent"  
    11.         android:background="@color/white" />  
    12.   
    13. </LinearLayout>  
    第四步:创建TbsActivity.class

    [java] view plain copy
    1. import android.graphics.PixelFormat;  
    2. import android.os.Bundle;  
    3. import android.support.v7.app.AppCompatActivity;  
    4. import android.util.Log;  
    5. import android.view.KeyEvent;  
    6. import android.view.WindowManager;  
    7. import com.tencent.smtt.sdk.WebChromeClient;  
    8. import com.tencent.smtt.sdk.WebSettings;  
    9. import com.tencent.smtt.sdk.WebView;  
    10. import com.tencent.smtt.sdk.WebViewClient;  
    11. import com.xiong.tbs_x5.R;  
    12.   
    13. /** 
    14.  * Created by xiongwenwei@aliyun.com 
    15.  * CreateTime: 2017/1/13 
    16.  * Note:腾讯浏览服务 
    17.  */  
    18. public class TbsActivity extends AppCompatActivity{  
    19.       
    20.     private com.tencent.smtt.sdk.WebView webView;  
    21.     private String url = "http://3g.qq.com";  
    22.   
    23.     @Override  
    24.     protected void onCreate(Bundle savedInstanceState) {  
    25.         super.onCreate(savedInstanceState);  
    26.         setContentView(R.layout.activity_main);  
    27.         getWindow().setFormat(PixelFormat.TRANSLUCENT);//(这个对宿主没什么影响,建议声明)  
    28.         getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);  
    29.   
    30.         initView();  
    31.         loadUrl(url);  
    32.     }  
    33.   
    34.     private void initView() {  
    35.         webView = (com.tencent.smtt.sdk.WebView) findViewById(R.id.webView);  
    36.     }  
    37.   
    38.     private void loadUrl(String url) {  
    39.         WebSettings webSettings = webView.getSettings();  
    40.         webSettings.setJavaScriptEnabled(true);  
    41.         webView.loadUrl(url);  
    42.         webView.setWebViewClient(new WebViewClient() {  
    43.             @Override  
    44.             public boolean shouldOverrideUrlLoading(WebView view, String url) {  
    45.                 view.loadUrl(url);  
    46.                 return true;  
    47.             }  
    48.   
    49.             @Override  
    50.             public void onReceivedError(WebView var1, int var2, String var3, String var4) {  
    51.                 Log.i("打印日志","网页加载失败");  
    52.             }  
    53.         });  
    54.         //进度条  
    55.         webView.setWebChromeClient(new WebChromeClient() {  
    56.             @Override  
    57.             public void onProgressChanged(WebView view, int newProgress) {  
    58.                 if (newProgress == 100) {  
    59.                     Log.i("打印日志","加载完成");  
    60.                 }  
    61.             }  
    62.         });  
    63.     }  
    64.   
    65.     @Override  
    66.     protected void onDestroy() {  
    67.         super.onDestroy();  
    68.         if (webView != null) webView.destroy();  
    69.     }  
    70.   
    71.     @Override  
    72.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
    73.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
    74.             if (webView != null && webView.canGoBack()) {  
    75.                 webView.goBack();  
    76.                 return true;  
    77.             }  
    78.             return super.onKeyDown(keyCode, event);  
    79.         }  
    80.         return super.onKeyDown(keyCode, event);  
    81.     }  
    82.       
    83. }  

    【接入成功效果】

    上述代码只是最基础的集成,更多的效果,请移步官网 [官网接入文档]

    大概试了下,APP第一次启动好像用的还是自带Webview,猜测是X5内核还没下载完吧

    接入成功,标志:1.长按文字会出现"保存离线网页" 2.复制英文会出现"翻译" 3.复制文字会有水滴标志






    展开全文
  • 大家都不知道原生的WebView 存在各种坑。...分别是:腾讯X5内核 和 crosswalk crosswalk : 据说很强大,但缺点就是会让你的APK包增大很多。(我还没试过,都是看大神们的博客说的) 大家可以参考这篇...

    大家都不知道原生的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包是放在 src\main\jniLibs  下这个可以看一下官方包。就知道了

    在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视频播放器接入...等等。官方描述还是很清晰的

     

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

     

     

    展开全文
  • 前言 由于是使用的腾讯的浏览服务,所以这里大部分介绍的是官网的...官网地址是 https://x5.tencent.com 微信公众号:腾讯浏览服务 论坛 http://bbs.mb.qq.com/forum-112-1.html ( 开发者反馈论坛 ) 反馈 http...

    前言

    由于是使用的腾讯浏览服务,所以这里大部分介绍的是官网的一些东西,不过自己会做一些复杂使用部分的实现,不至于像官网上介绍的笼统。


    联系方式

    这里用的是TBS腾讯浏览服务。

    官网地址是 https://x5.tencent.com

    微信公众号:腾讯浏览服务

    论坛 http://bbs.mb.qq.com/forum-112-1.html ( 开发者反馈论坛 )

    反馈 http://bbs.mb.qq.com/newthread?fid=112


    背景

    这里介绍一下x5内核相对Android系统内核的一些优势

    • TBS(腾讯浏览服务)的优势

    1) 速度快:相比系统webview的网页打开速度有30+%的提升;
    2) 省流量:使用云端优化技术使流量节省20+%;
    3) 更安全:安全问题可以在24小时内修复;
    4) 更稳定:经过亿级用户的使用考验,CRASH率低于0.15%;
    5) 兼容好:无系统内核的碎片化问题,更少的兼容性问题;
    6) 体验优:支持夜间模式、适屏排版、字体设置等浏览增强功能;
    7) 功能全:在Html5、ES6上有更完整支持;
    8) 更强大:集成强大的视频播放器,支持视频格式远多于系统webview;
    9) 视频和文件格式的支持x5内核多于系统内核;
    10) 防劫持是x5内核的一大亮点

    • 运行环境

    1)手机ROM版本高于或等于2.2版本;
    2)手机RAM大于500M,该RAM值通过手机 /proc/meminfo 文件的MemTotal动态获取
    注:如果不满足上述条件,SDK会自动切换到系统WebView,SDK使用者不用关心该切换过程。

    • SDK尺寸指标

    1)SDK提供的JAR包约250K


    SDK下载

    我们肯定需要先下载sdk的jar包,然后才能使用该sdk的功能,也就是这里的x5内核。

    腾讯浏览服务的sdk下载链接是:腾讯SDK下载页。这里我选择的是第三个(完整版+文件能力的Android SDK),当然选择第一个也可以,只不过不带有文件能力。第二个适用于快速接入TBS且常规使用WebView的开发者。因为我这里可能还涉及到与html网页的交互,为了方便,就没有选择第二个。因为第一个和第三个都只是单纯的将x5的内核替换系统的内核,其他没有太多的变化。像一些基本的设置也都和系统内核的是一样的,只不过x5的内核优势很明显。


    SDK集成

    sdk下载完成后,解压如下图所示:
    这里写图片描述

    里面有文件常见问题解答文档和文件方案接口介绍文档。因为是带有文件能力的sdk,所以有这些文档,文档也比较简单,写的很基础,这里不多介绍了。

    这里我们用到的是jar包,我标注在图中了。将jar包添加到我们的项目中,就可以使用对应的功能了。

    将jar包放到libs目录下:
    这里写图片描述

    然后记得添加jar包依赖,如下:
    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    经过上面几个步骤之后,你的项目就集成了该sdk,可以使用x5的内核了。


    使用

    用到的所有原生WebView导入的类和接口都改导入 com.tencent.smtt.sdk 里面的类,类接口名对应。这样就相当于用x5的内核替换了系统的内核。

    需要注意的是:

    1)请不要在代码里使用下述写法

    import android.*;
    import android.webkit.*;
    import android.webkit.WebStorage.*;
    import android.net.*;
    import android.net.http.*;

    2)除了源码里需要把相关的包名和类名进行替换,布局xml里面的声明也需要替换,例如:

    <com.tencent.smtt.sdk.WebView
    android:id="@+id/forum_context"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingLeft="5dp"
    android:paddingRight="5dp" />

    当然,你要是不在布局里面声明,而是自己在代码中new出来,添加的x5内核,那么就不用管xml布局。这里推荐大家用这种方法来实现,会比在xml布局中声明更加的灵活方便。

    替换不完全时,可能发生的问题是关于cookie的身份错误、类转换时的crash等。cookie问题产生的原理是:一段代码把cookie塞给了系统内核,另外一段代码尝试从x5的内核里读取cookie就失败了。类转换的错误产生的原理是:比如xml里指定的是系统的webview,java的代码里把它当作x5的webview使用。

    然后大家自己原来已经用的系统的内核,再替换为x5的内核需要你仔细一点,别忘记替换包名,不然就会发生上面的错误。如果刚开始就使用的就是集成的x5内核,那么就不用太担心,不过选择导包的时候还是需要注意别用系统的内核,要使用腾讯提供的x5内核。

    x5暂时不提供64位so文件,为了保证64位手机能正常加载x5内核,请参照如下链接修改相关配置https://x5.tencent.com/tbs/technical.html#/detail/sdk/1/34cf1488-7dc2-41ca-a77f-0014112bcab7

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

    优化异常上报:

    为了提高合作方的webview场景稳定性,及时发现并解决x5相关问题,当客户端发生crash等异常情况并上报给服务器时请务必带上x5内核相关信息。x5内核异常信息获取接口为:com.tencent.smtt.sdk.WebView.getCrashExtraMessage(context)。以bugly日志上报为例:

    UserStrategy strategy = new UserStrategy(appContext);
      strategy.setCrashHandleCallback(new CrashReport.CrashHandleCallback() {
        public Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
          LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
          String x5CrashInfo = com.tencent.smtt.sdk.WebView.getCrashExtraMessage(appContext);
          map.put("x5crashInfo", x5CrashInfo);
          return map;
        }
        @Override
        public byte[] onCrashHandleStart2GetExtraDatas(int crashType, String errorType, String errorMessage, String errorStack) {
          try {
            return "Extra data.".getBytes("UTF-8");
          } catch (Exception e) {
            return null;
          }
        }
      });
      CrashReport.initCrashReport(appContext, APPID, true, strategy);

    适配修改:

    1) App 首次就可以加载 x5 内核

    App 在启动后(例如在 Application 的 onCreate 中)立刻调用 QbSdk 的预加载接口 initX5Environment ,可参考接入示例,第一个参数传入 context,第二个参数传入 callback,不需要 callback 的可以传入 null,initX5Environment 内部会创建一个线程向后台查询当前可用内核版本号,这个函数内是异步执行所以不会阻塞 App 主线程,这个函数内是轻量级执行所以对 App 启动性能没有影响,当 App 后续创建 webview 时就可以首次加载 x5 内核了

    package com.example.administrator.firststeppro.application;
    
    import android.app.Application;
    
    import com.tencent.smtt.sdk.QbSdk;
    
    /**
     * 自定义MyApplication类继承Application
     * 并重写onCreate方法完成一些初始化加载操作
     */
    public class MyApplication extends Application{
    
        @Override
        public void onCreate() {
            super.onCreate();
            preinitX5WebCore();
        }
    
        /**
         * 预加载x5内核
         */
        private void preinitX5WebCore() {
            if (!QbSdk.isTbsCoreInited()){
                // 这个函数内是异步执行所以不会阻塞 App 主线程,这个函数内是轻量级执行所以对 App 启动性能没有影响
                QbSdk.initX5Environment(this, null);
            }
        }
    }
    

    别忘记在清单配置文件中声明该Application:

    <application
            android:name=".application.MyApplication"
            android:largeHeap="true"
            android:allowBackup="true"
            android:icon="@mipmap/app_icon"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity
                android:name=".activity.SplashActivity"
                android:screenOrientation="portrait">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".activity.MainActivity"
                android:windowSoftInputMode="stateHidden|adjustResize"
                android:configChanges="screenSize|orientation|keyboardHidden"
                android:screenOrientation="portrait"/>
    
        </application>

    设置name属性即可。

    2) 目前,由于SDK WebView所提供的WebView类,是对系统WebView的聚合包装,所以:获取系统内核的WebView或者 x5内核的WebView的宽高

    android.webkit.WebView webView = new android.webkit.WebView(this);
    int width = webView.getWidth();

    需要采用下面的方式进行

    com.tencent.smtt.sdk.WebView webView = new com.tencent.smtt.sdk.WebView(this);
    int width = webView.getView().getWidth();

    调整cookie的使用:

    com.tencent.smtt.sdk.CookieManager和com.tencent.smtt.sdk.CookieSyncManager的相关接口的调用,在接入SDK后,需要放到创建X5的WebView之后(也就是X5内核加载完成)进行;否则,cookie的相关操作只能影响系统内核。

    兼容视频播放:

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

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

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

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

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

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

    声明当前<item name="android:windowIsTranslucent">false为不透明。
    特别说明:这个视各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 的说明

    如果 app 需要自定义 UA,建议采取在 SDK 默认UA 后追加 app UA 的方式示例:

    webSetting.setUserAgentString(webSetting.getUserAgentString() + APP_NAME_UA);
    其中 APP_NAME_UA 是 app 自定义 UA

    由于我们提供的 TBS jar 已经混淆过,所以 App 混淆时可以不再混淆我们的 TBS jar


    代码实现

    下面我给出我自己的项目中使用x5内核加载的网页,顺便也测试一下是否成功的加载了x5内核。

    package com.example.administrator.firststeppro.fragment;
    
    
    import android.Manifest;
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.graphics.Color;
    import android.graphics.PixelFormat;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.app.Fragment;
    import android.support.annotation.NonNull;
    import android.view.Gravity;
    import android.view.KeyEvent;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.tencent.smtt.export.external.extension.interfaces.IX5WebViewExtension;
    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.export.external.interfaces.WebResourceResponse;
    import com.tencent.smtt.sdk.WebSettings;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    import android.widget.LinearLayout;
    import android.widget.Toast;
    
    import com.example.administrator.firststeppro.R;
    import com.example.administrator.firststeppro.base.BaseFragment;
    import com.example.administrator.firststeppro.orm.AndroidToJs;
    import com.example.administrator.firststeppro.utils.LogUtil;
    import com.example.administrator.firststeppro.utils.ToastUtil;
    
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
    
    /**
     * A simple {@link Fragment} subclass.
     * 展示个人的csdn博客主页
     */
    public class PageOneFragment extends BaseFragment {
    
        @BindView(R.id.linear_page1_webview)LinearLayout linear_page1_webiew;// webView的父布局
        @BindView(R.id.material_progress_bar)MaterialProgressBar material_progress_bar;
    
        private boolean isPrepared = false;// 是否已经准备好要加载数据
        private static WebView webView = null;
        private WebSettings webSettings;// WebSettings对象
    
        public PageOneFragment() {
            // Required empty public constructor
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_page_one, container, false);
            getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);// 加载网页视频避免闪屏和透明
            ButterKnife.bind(this, view);
    
            isPrepared = true;
    
            setLazyLoad();
    
            requestPermission();// 申请权限
    
            return view;
        }
    
        @SuppressLint("NewApi")
        private void requestPermission() {
            if(getContext().checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
                // 进行授权
                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            switch (requestCode){
                case 1:
                    if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
    
                    }else {
                        ToastUtil.showToast(getContext(), "读写文件权限未开启");
                    }
                    break;
            }
        }
    
    
        /*
        @OnClick({R.id.btn_callJs})
        public void doClick(View view){
            switch (view.getId()){
                case R.id.btn_callJs:// Android调用js方法
                    webView.post(new Runnable() {
                        @Override
                        public void run() {
                            // 调用index.html文件的callJS()方法
    //                        webView.loadUrl("javascript:callJS()");
    
                            // 不同版本兼容4.4以上
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                                webView.evaluateJavascript("index:callJS()", new ValueCallback<String>() {
                                    @Override
                                    public void onReceiveValue(String value) {
                                        // 此处为js返回的结果
                                        LogUtil.e("TAG","" + value);
                                    }
                                });
                            }else {
                                webView.loadUrl("index:callJS()");
                            }
    
                        }
                    });
                    break;
            }
        }
        */
    
        @Override
        protected void setLazyLoad() {
            super.setLazyLoad();
            if (isVisible && isPrepared){
                LogUtil.e("TAG","loadDataPage1");
                if (webView == null){
                    openWebViewPage();
                }
            }
        }
    
        /**
         * 打开webView页面
         */
        private void openWebViewPage() {
            // 创建WebView对象添加到布局中
            webView = new WebView(getContext().getApplicationContext());
    
            IX5WebViewExtension ix5WebViewExtension = webView.getX5WebViewExtension();
            ix5WebViewExtension.setScrollBarFadingEnabled(false);
    
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            webView.setLayoutParams(params);
            linear_page1_webiew.addView(webView);
    
            // 清除网页访问留下的缓存
            // 由于内核缓存是全局的因此这个方法不仅仅针对webView而是针对整个应用程序
            webView.clearCache(true);
    
            // 清除当前webView的访问历史记录
            webView.clearHistory();
    
            // 这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
            webView.clearFormData();
    
            // https://www.panda.tv/
            // https://blog.csdn.net/csdnzouqi
            // http://soft.imtt.qq.com/browser/tes/feedback.html
    //        String url = "file:////android_asset/index.html";// 加载主页面的url
            String url = "http://soft.imtt.qq.com/browser/tes/feedback.html";// 邹奇的博客主页
    
    
            // 获取WebSettings对象
            webSettings = webView.getSettings();
            // 特别注意:5.1以上默认禁止了https和http混用。下面代码是开启
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 21
    
            }
            webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);// 不使用缓存,直接用网络加载
            webSettings.setJavaScriptEnabled(true);// webView支持javascript
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 告诉js可以自动打开window
    
            // 两者一起使用,可以让html页面加载显示适应手机的屏幕大小
            webSettings.setUseWideViewPort(true);
            webSettings.setLoadWithOverviewMode(true);
    
            webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
    //        webSettings.setAllowFileAccess(true); //设置可以访问文件
            webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
            webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
    
            // 即允许在 File 域下执行任意 JavaScript 代码
    //        webSettings.setAllowFileAccess(true);// 设置是否允许 WebView 使用 File 协议
            // 禁止 file 协议加载 JavaScript
    //        if (url.startsWith("file://")){
    //            webSettings.setJavaScriptEnabled(false);
    //        }else {
    //            webSettings.setJavaScriptEnabled(true);
    //        }
    
            webSettings.setSavePassword(false);// 关闭密码保存提醒;该方法在以后的版本中该方法将不被支持
    
            webSettings.setDomStorageEnabled(true);// 设置支持DOM storage API
    
            // 通过addJavascriptInterface()将Java对象映射到JS对象
            webView.addJavascriptInterface(new AndroidToJs(getContext()), "androidObj");
    
            // 加载手机本地的html
    //        webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
    
            // 加载html页面的一小段内容 ('#','%', '\', '?' 分别用 %23, %25, %27, %3f 替换)
    //        webView.loadData("显示内容", "text/html", "utf-8");
    
            //设置WebViewClient类
            webView.setWebViewClient(new WebViewClient(){
    
                // 设置不用系统浏览器打开,直接显示在当前 webview
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    // 如果不是http或者https开头的url,那么使用手机自带的浏览器打开
                    if (!url.startsWith("http://") && !url.startsWith("https://")){
                        try {
                            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                            startActivity(intent);
                            return true;
                        }catch (Exception e){
                            e.printStackTrace();
                            return true;
                        }
                    }
                    view.loadUrl(url);
                    return false;
    //                return super.shouldOverrideUrlLoading(view, url);
                }
    
                @Override
                public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) {
                    super.onReceivedSslError(webView, sslErrorHandler, sslError);
                }
            });
    
    
            //设置WebChromeClient类
    
            webView.setWebChromeClient(new WebChromeClient(){
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
    
                    // 加载完成,隐藏进度条
                    if (newProgress == 100){
                        material_progress_bar.setVisibility(View.GONE);
                    }else {
                        material_progress_bar.setVisibility(View.VISIBLE);
                    }
    
                }
    
                //            // 拦截js的警告框
    //
    //            @Override
    //            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
    //
    ////                ToastUtil.showToast(getContext(), "拦截js alert");
    //                new AlertDialog.Builder(getContext())
    //                        .setTitle("弹框")
    //                        .setMessage(message)
    //                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
    //                            @Override
    //                            public void onClick(DialogInterface dialog, int which) {
    //                                result.confirm();
    //                            }
    //                        })
    //                        .setCancelable(false)
    //                        .create().show();
    //
    //                return true;
    ////                return super.onJsAlert(view, url, message, result);
    //            }
    //
    //            // 拦截js的确认框
    //            @Override
    //            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
    //                return super.onJsConfirm(view, url, message, result);
    //            }
    //
    //            // 拦截输入框
    //            @Override
    //            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    //
    ////                ToastUtil.showToast(getContext(), ""+ message);
    //                // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
    //                // 假定传入进来的 url = "js://android?arg1=1&arg2=2"(同时也是约定好的需要拦截的)
    //                Uri uri = Uri.parse(message);
    //
    //                if (uri.getScheme().equals("js")){
    //
    //                    if (uri.getAuthority().equals("android")){
    //                        ToastUtil.showToast(getContext(),"Android端拦截成功!");
    //
    //                        // 可以在协议上带有参数并传递到Android上
    ////                        HashMap<String, String> params = new HashMap<>();
    ////                        Set<String> collection = uri.getQueryParameterNames();
    //
    //                        // 这里可以执行js所需要调用的逻辑
    //
    //                        // 返回值
    //                        result.confirm("Android端返回给js的内容");
    //                    }
    //
    //                }
    //
    //                return true;
    ////                return super.onJsPrompt(view, url, message, defaultValue, result);
    //            }
            });
    
            // 加载apk包中的html页面
            webView.loadUrl(url);
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            isPrepared = false;// 视图销毁的时候恢复数据加载状态
        }
    
        @Override
        public void onHiddenChanged(boolean hidden) {
            super.onHiddenChanged(hidden);
            if (!hidden){
                LogUtil.e("TAG", "onHiddenChanged1");
            }
        }
    
    
        // 先让 WebView 加载null内容,然后移除 WebView,再销毁 WebView,最后置空
        private void clearWebView() {
            if (webView != null){
                webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
                webView.clearHistory();
                webView.clearCache(true);// 清除缓存
    
                ((ViewGroup)webView.getParent()).removeView(webView);
                webView.destroy();
                webView = null;
            }
        }
    
        /**
         * fragment的点击事件,参数由当前fragment所依附的activity传过来
         * @param keyCode
         * @param event
         * @param context
         */
        public static void onKeyDown(int keyCode, KeyEvent event, Context context) {
            if (webView != null){
                if (webView.canGoBack()){
                    webView.goBack();
                }else {
                    view_toast_exit = LayoutInflater.from(context).inflate(R.layout.view_toast_exit, null);
                    exitApp(2000, context);
                }
            }
        }
    
        private static Toast toast = null;// 创建Toast对象
        private static long firstTime;// 记录点击返回时第一次的时间毫秒值
        private static View view_toast_exit;// 吐丝,退出应用的view
    
        /**
         * 退出应用
         * @param timeInterval 设置第二次点击退出的时间间隔
         * @param context
         */
        private static void exitApp(long timeInterval, Context context) {
            if(System.currentTimeMillis() - firstTime >= timeInterval){
                if (view_toast_exit != null){
                    toast = new Toast(context);
                    toast.setView(view_toast_exit);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.setDuration(Toast.LENGTH_SHORT);
                    toast.show();
                }else {
                    ToastUtil.showToast(context, "再按一次退出程序");
                }
    
    //            ToastUtil.showToast(this, "再按一次退出程序");
                firstTime = System.currentTimeMillis();
            }else {
                if (toast != null){
                    toast.cancel();
                }
    //            finish();// 销毁当前activity
                System.exit(0);// 完全退出应用
            }
        }
    }
    

    那么怎么判断是否加载了x5内核呢?

    • webview的getX5WebViewExtension()返回非null表示已加载了x5内核webview

    • 您的app打开网页http://soft.imtt.qq.com/browser/tes/feedback.html,显示000000表示加载的是系统内核,显示大于零的数字表示加载了x5内核(该数字是x5内核版本号)

    上面我加载的url就是http://soft.imtt.qq.com/browser/tes/feedback.html,让我们运行一下看看效果:

    这里写图片描述

    可以看到确实是成功的加载了x5的内核。


    A little bit of progress every day!Come on!

    展开全文
  • 前言:以前在访问网页的时候用的都是Android系统提供的WebView,而且使用WebView的时候可能还会遇到很多坑,今天试了一下腾讯的X5WebView感觉很不错,贴张效果图哈~ 下面就看一下如何把X5WebView集成到工程中。 ...

    前言:以前在访问网页的时候用的都是Android系统提供的WebView,而且使用WebView的时候可能还会遇到很多坑,今天试了一下腾讯的X5WebView感觉很不错,贴张效果图哈~
    这里写图片描述
    下面就看一下如何把X5WebView集成到工程中。
    使用X5WebView首先我们需要到官方网站上去下载它的SDK,下载地址:http://x5.tencent.com/tbs/sdk.html
    下载完之后我们新建一个项目,就叫X5WebViewTest吧。
    把下载下来的SDK解压,然后把里面的tbs_sdk_thirdapp_v3.6.0.1249_43610_sharewithdownload_withoutGame_obfs_20180608_114954.jar放到项目中的libs中,再把SDK接入示例-Android Studio解压把里面的jniLibs复制到我们项目中main下,最后同步一下。
    然后打开AndroidManifest.xml配置如下

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.ranlegeran.x5webviewtest">
    
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <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" />
    
        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    需要定义一个Application类如下

    package com.ranlegeran.x5webviewtest;
    
    import android.app.Application;
    import android.util.Log;
    
    import com.tencent.smtt.sdk.QbSdk;
    
    public class MyApplication extends Application {
        private static final String TAG = "MyApplication";
    
        @Override
        public void onCreate() {
            super.onCreate();
            //搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
            QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
    
                @Override
                public void onViewInitFinished(boolean arg0) {
                    //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
                    Log.e(TAG, " onViewInitFinished " +arg0);
                }
    
                @Override
                public void onCoreInitFinished() {
    
                }
            };
            //x5内核初始化接口
            QbSdk.initX5Environment(getApplicationContext(),  cb);
        }
    }
    

    接着定义X5WebView类

    package com.ranlegeran.x5webviewtest;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.util.AttributeSet;
    
    import com.tencent.smtt.sdk.WebSettings;
    import com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    
    public class X5WebView extends WebView {
    
        private WebViewClient client = new WebViewClient() {
            /**
             * 防止加载网页时调起系统浏览器
             */
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        };
    
        @SuppressLint("SetJavaScriptEnabled")
        public X5WebView(Context arg0, AttributeSet arg1) {
            super(arg0, arg1);
            this.setWebViewClient(client);
            initWebViewSettings();
            this.getView().setClickable(true);
        }
    
        private void initWebViewSettings() {
            WebSettings mWebSettings = this.getSettings();
            mWebSettings.setJavaScriptEnabled(true);
            mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
            mWebSettings.setAllowFileAccess(true);
            mWebSettings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
            mWebSettings.setSupportZoom(true);
            mWebSettings.setBuiltInZoomControls(true);
            mWebSettings.setUseWideViewPort(true);
            mWebSettings.setSupportMultipleWindows(true);
            mWebSettings.setAppCacheEnabled(true);
            mWebSettings.setDomStorageEnabled(true);
            mWebSettings.setGeolocationEnabled(true);
            mWebSettings.setAppCacheMaxSize(Long.MAX_VALUE);
            mWebSettings.setPluginState(WebSettings.PluginState.ON_DEMAND);
            mWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        }
    
        public X5WebView(Context arg0) {
            super(arg0);
            setBackgroundColor(85621);
        }
    }
    

    打开activity_main.xml把刚才定义的X5WebView放进来

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
       <com.ranlegeran.x5webviewtest.X5WebView
           android:id="@+id/mX5WebView"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
       </com.ranlegeran.x5webviewtest.X5WebView>
    
    </LinearLayout>

    最后就是MainActivity部分了

    package com.ranlegeran.x5webviewtest;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.KeyEvent;
    
    public class MainActivity extends AppCompatActivity {
        private X5WebView mX5WebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mX5WebView = (X5WebView) findViewById(R.id.mX5WebView);
            mX5WebView.loadUrl("https://portal.3g.qq.com/");
    
        }
    
        /**
         * 返回上个页面
         * @param keyCode
         * @param event
         * @return
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (mX5WebView != null && mX5WebView.canGoBack()) {
                    mX5WebView.goBack();
                    return true;
                } else {
                    return super.onKeyDown(keyCode, event);
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
    
        @Override
        protected void onDestroy() {
            //释放资源
            if (mX5WebView != null)
                mX5WebView.destroy();
            super.onDestroy();
        }
    
    }
    
    展开全文
  • 基于腾讯X5内核 目前已有功能: 1、文件浏览(支持pdf/ppt/doc/excel/txt) 2、文件上传(JS) 3、文件下载 4、Android与JS交互 5、自定义交互(进度条、下拉回弹) 6、视频播放 1、添加依赖和配置 根目录build....
  • 腾讯官网:...一.AndroidStudio接入X5WebView 1.添加so以及lib文件 2.Gradle配置 apply plugin: 'com.android.application' android { compileSdkV...

    腾讯官网:https://x5.tencent.com/tbs/guide/sdkInit.html

     

     

    一.AndroidStudio接入X5WebView

     

     

    <1> 添加so以及lib文件

     

     

     

    <2> Gradle配置

     

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 28
        defaultConfig {
            
            ndk {
                abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
            }
        }
    
    
        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    
    
    }
    
    

     

     

    <3> 权限

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

     

     

    <4> 自定义X5WebView

    public class X5WebView extends WebView {
    	TextView title;
    	private WebViewClient client = new WebViewClient() {
    		/**
    		 * 防止加载网页时调起系统浏览器
    		 */
    		public boolean shouldOverrideUrlLoading(WebView view, String url) {
    			view.loadUrl(url);
    			return true;
    		}
    	};
    
    	@SuppressLint("SetJavaScriptEnabled")
    	public X5WebView(Context arg0, AttributeSet arg1) {
    		super(arg0, arg1);
    		this.setWebViewClient(client);
    		// this.setWebChromeClient(chromeClient);
    		// WebStorage webStorage = WebStorage.getInstance();
    		initWebViewSettings();
    		this.getView().setClickable(true);
    	}
    
    	private void initWebViewSettings() {
    		WebSettings webSetting = this.getSettings();
    		webSetting.setJavaScriptEnabled(true);
    		webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
    		webSetting.setAllowFileAccess(true);
    		webSetting.setLayoutAlgorithm(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.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
    		// settings 的设计
    	}
    
    	@Override
    	protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    		boolean ret = super.drawChild(canvas, child, drawingTime);
    		canvas.save();
    		Paint paint = new Paint();
    		paint.setColor(0x7fff0000);
    		paint.setTextSize(24.f);
    		paint.setAntiAlias(true);
    		if (getX5WebViewExtension() != null) {
    			canvas.drawText(this.getContext().getPackageName() + "-pid:"
    					+ android.os.Process.myPid(), 10, 50, paint);
    			canvas.drawText(
    					"X5  Core:" + QbSdk.getTbsVersion(this.getContext()), 10,
    					100, paint);
    		} else {
    			canvas.drawText(this.getContext().getPackageName() + "-pid:"
    					+ android.os.Process.myPid(), 10, 50, paint);
    			canvas.drawText("Sys Core", 10, 100, paint);
    		}
    		canvas.drawText(Build.MANUFACTURER, 10, 150, paint);
    		canvas.drawText(Build.MODEL, 10, 200, paint);
    		canvas.restore();
    		return ret;
    	}
    
    	public X5WebView(Context arg0) {
    		super(arg0);
    		setBackgroundColor(85621);
    	}
    
    }

     

     

     

    <5> Application代码

    package com.wjn.customwebviewjs;
    
    import android.app.Application;
    import android.util.Log;
    
    import com.tencent.smtt.sdk.QbSdk;
    
    public class MyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            //搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
            QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
    
                @Override
                public void onViewInitFinished(boolean arg0) {
                    // TODO Auto-generated method stub
                    //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
                    Log.d("app", " onViewInitFinished is " + arg0);
                }
    
                @Override
                public void onCoreInitFinished() {
                    // TODO Auto-generated method stub
                }
            };
            //x5内核初始化接口
            QbSdk.initX5Environment(getApplicationContext(),  cb);
    
        }
    }
    

     

     

    <6> Activity代码

    package com.wjn.customwebviewjs;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.ProgressBar;
    
    import com.tencent.smtt.sdk.WebChromeClient;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    
    public class X5WebViewActivity extends AppCompatActivity {
    
        private ProgressBar progressBar;
        private X5WebView x5WebView;
        private String url = "https://blog.csdn.net/weixin_37730482";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
            initHardwareAccelerate();
            initView();
        }
    
        /**
         * 启用硬件加速
         */
    
        private void initHardwareAccelerate() {
            try {
                if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
                    getWindow()
                            .setFlags(
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
                }
            } catch (Exception e) {
            }
        }
    
        /**
         * 初始化各种View
         * */
    
        private void initView() {
            progressBar=findViewById(R.id.activity_x5webview_progressbar);
            x5WebView = findViewById(R.id.activity_x5webview_x5webview);
            x5WebView.loadUrl(url);
            x5WebView.setWebViewClient(new myWebViewClient());
            x5WebView.setWebChromeClient(new myWebChromeClient());
        }
    
        /**
         * WebViewClient监听
         * */
    
        private class myWebViewClient extends WebViewClient{
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String s) {
                webView.loadUrl(s);
                return true;
            }
        }
    
        /**
         * WebChromeClient监听
         * */
    
        private class myWebChromeClient extends WebChromeClient{
    
            @Override
            public void onProgressChanged(WebView webView, int i) {
                super.onProgressChanged(webView, i);
                if (i == 100) {
                    progressBar.setVisibility(View.GONE);//加载完网页进度条消失
                } else {
                    progressBar.setVisibility(View.VISIBLE);//开始加载网页时显示进度条
                    progressBar.setProgress(i);//设置进度值
                }
            }
        }
    
        /**
         * onKeyDown方法
         */
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (x5WebView != null && x5WebView.canGoBack()) {
                    x5WebView.goBack();
                    return true;
                } else {
                    return super.onKeyDown(keyCode, event);
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        /**
         * onDestroy方法
         * */
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(null!=x5WebView){
                x5WebView.destroy();//释放资源
            }
        }
    
    }
    

     

     

    <7> 效果

     

     

     

     

     

     

     

    二.Android与JS通过X5WebView完成交互

     

    X5WebView是腾讯封装的WebView,增加了很多的功能。但是Android与JS通过X5WebView交互和原生的WebView是一样的。

     

     

    <1> Android 调用 JS (loadUrl为例)

     

    JS代码

    <script language="JavaScript" type="text/javascript">
    
        var nowDate = new Date();
    
        var nH=nowDate.getHours();
    
        var nM=nowDate.getMinutes();
    
        var nS=nowDate.getSeconds();
    
        function MyOnclick() {
    
            document.write("当前时间:" + nH+ ":" + nM + ":" + nS);
    
       }
    
    </script>
    

     

     

    Android代码

    package com.wjn.customwebviewjs;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    import com.tencent.smtt.sdk.WebChromeClient;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    
    public class X5WebViewActivity extends AppCompatActivity {
    
        private TextView textView;
        private ProgressBar progressBar;
        private X5WebView x5WebView;
        private String url = "file:///android_asset/abc.html";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
            initHardwareAccelerate();
            initView();
        }
    
        /**
         * 启用硬件加速
         */
    
        private void initHardwareAccelerate() {
            try {
                if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
                    getWindow()
                            .setFlags(
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
                }
            } catch (Exception e) {
            }
        }
    
        /**
         * 初始化各种View
         * */
    
        private void initView() {
            textView=findViewById(R.id.activity_x5webview_textview);
            progressBar=findViewById(R.id.activity_x5webview_progressbar);
            x5WebView = findViewById(R.id.activity_x5webview_x5webview);
            x5WebView.loadUrl(url);
            x5WebView.setWebViewClient(new myWebViewClient());
            x5WebView.setWebChromeClient(new myWebChromeClient());
    
            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    x5WebView.loadUrl("javascript:MyOnclick()");
                }
            });
        }
    
        /**
         * WebViewClient监听
         * */
    
        private class myWebViewClient extends WebViewClient{
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String s) {
                webView.loadUrl(s);
                return true;
            }
        }
    
        /**
         * WebChromeClient监听
         * */
    
        private class myWebChromeClient extends WebChromeClient{
    
            @Override
            public void onProgressChanged(WebView webView, int i) {
                super.onProgressChanged(webView, i);
                if (i == 100) {
                    progressBar.setVisibility(View.GONE);//加载完网页进度条消失
                } else {
                    progressBar.setVisibility(View.VISIBLE);//开始加载网页时显示进度条
                    progressBar.setProgress(i);//设置进度值
                }
            }
        }
    
        /**
         * onKeyDown方法
         */
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (x5WebView != null && x5WebView.canGoBack()) {
                    x5WebView.goBack();
                    return true;
                } else {
                    return super.onKeyDown(keyCode, event);
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        /**
         * onDestroy方法
         * */
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(null!=x5WebView){
                x5WebView.destroy();//释放资源
            }
        }
    
    }
    

     

     

    效果

     

    点击前

     

    点击后

     

     

     

     

    <2> JS 调用 Android (addJavascriptInterface为例)

     

     

    JS代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="Content-Language" content="zh-cn"/>
    
    <title>Android WebView 与 Javascript 交互</title>
    <head>
        <style>
      body {background-color:#e6e6e6}
     
      .rect
      {
        color:white;
        font-family:Verdana, Arial, Helvetica, sans-serif;
        font-size:16px;
        width:100px;
        padding:6px;
        background-color:#98bf21;
        text-decoration:none;
        text-align:center;
        border:none;
        cursor:pointer;
      }
     
      .inputStyle {font-size:16px;padding:6px}
    
    
        </style>
    </head>
    
    <body>
    <p>测试Android WebView 与 Javascript 交互</p>
    <input id="name_input" class="inputStyle" type="text"/>
    <a class="rect" onclick="sendInfoToJava()">JS调用Java</a>
    
    <script>
    
      function sendInfoToJava(){
        //调用android程序中的方法,并传递参数
        var name = document.getElementById("name_input").value;
        window.AndroidWebView.showInfoFromJs(name);
      }
    
    
    </script>
    
    </body>
    </html>
    

     

     

    Android代码

    package com.wjn.customwebviewjs;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.tencent.smtt.sdk.WebChromeClient;
    import com.tencent.smtt.sdk.WebView;
    import com.tencent.smtt.sdk.WebViewClient;
    
    public class X5WebViewActivity extends AppCompatActivity {
    
        private ProgressBar progressBar;
        private X5WebView x5WebView;
        private String url = "file:///android_asset/hhh.html";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_x5webview);
            initHardwareAccelerate();
            initView();
        }
    
        /**
         * 启用硬件加速
         */
    
        private void initHardwareAccelerate() {
            try {
                if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
                    getWindow()
                            .setFlags(
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                                    android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
                }
            } catch (Exception e) {
            }
        }
    
        /**
         * 初始化各种View
         * */
    
        private void initView() {
            progressBar=findViewById(R.id.activity_x5webview_progressbar);
            x5WebView = findViewById(R.id.activity_x5webview_x5webview);
            x5WebView.loadUrl(url);
            x5WebView.setWebViewClient(new myWebViewClient());
            x5WebView.setWebChromeClient(new myWebChromeClient());
            // 添加js交互接口类,并起别名 AndroidWebView
            x5WebView.addJavascriptInterface(new JavascriptInterface(this), "AndroidWebView");
        }
    
        /**
         * Native JS 接口
         */
    
        @SuppressLint("JavascriptInterface")
        public class JavascriptInterface {
    
            /**
             * 构造方法
             */
    
            private Context context;
            public JavascriptInterface(Context context) {
                this.context = context;
            }
    
            /**
             * JS 调用 Android
             */
    
            @android.webkit.JavascriptInterface
            public void showInfoFromJs(String name) {
                Toast.makeText(context, "JS页面输入内容:" + name, Toast.LENGTH_LONG).show();
            }
    
        }
    
        /**
         * WebViewClient监听
         * */
    
        private class myWebViewClient extends WebViewClient{
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String s) {
                webView.loadUrl(s);
                return true;
            }
        }
    
        /**
         * WebChromeClient监听
         * */
    
        private class myWebChromeClient extends WebChromeClient{
    
            @Override
            public void onProgressChanged(WebView webView, int i) {
                super.onProgressChanged(webView, i);
                if (i == 100) {
                    progressBar.setVisibility(View.GONE);//加载完网页进度条消失
                } else {
                    progressBar.setVisibility(View.VISIBLE);//开始加载网页时显示进度条
                    progressBar.setProgress(i);//设置进度值
                }
            }
        }
    
        /**
         * onKeyDown方法
         */
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (x5WebView != null && x5WebView.canGoBack()) {
                    x5WebView.goBack();
                    return true;
                } else {
                    return super.onKeyDown(keyCode, event);
                }
            }
            return super.onKeyDown(keyCode, event);
        }
    
        /**
         * onDestroy方法
         * */
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(null!=x5WebView){
                x5WebView.destroy();//释放资源
            }
        }
    
    }
    

     

     

    效果

     

    由于X5WebView与原生WebView在Android与JS交互方式上是一样的,所以在这里就简单举例。

    Android与JS通过WebView交互详解 请看 Android与JS通过WebView相互调用详解

     

     

    附:代码下载:https://github.com/wujianning/CustomWebViewJS

    展开全文
  • 作为与js交互的优化之一,今天讲一下如何集成腾讯X5。 首先我们先了解一下TBS浏览服务: ###背景知识: 1. TBS(腾讯浏览服务)的优势 速度快:相比系统webview的网页打开速度有30+%的提升; 省流量:使用云端优化...
  • 首先说声抱歉,去年升级App版本到Android Q时,使用腾讯tbs在一加7plus,华为mate20上报错了,还吐槽了他们,不管最后还是通过降低版本到28解决了,最近发现腾讯X5WebView已经适配到Android Q了,于是尝试了一下,...
  • 最近把项目升级到AndroidX,项目的目标版本也升级到29,在各种机型上都没问题,部分AndroidQ的机型也测试没有问题,在出现一个奇怪的问题,第一次在真机上跑没有问题,打Release包也没问题,用360加固后跑起来一点...
  • 公司最近对接腾讯x5内核,按照官方文档一步一步走,很简单,提交QA。 正当愉快钓鱼的时候,QA说部分机型不能用。 https://x5.tencent.com/tbs/technical.html#/detail/sdk/1/34cf1488-7dc2-41ca-a77f-0014112bcab7 ...
  • 腾讯推出了最新的Q立方浏览器,Q立方浏览器搭载了腾讯基于开源Webkit深度优化的“X5内核”,在web/wap页面打开速度、省流量、UI和多窗口交互方式、Html5等方面都与现有的手机QQ浏览器有不同之处。  截图如下: PS...
  • Android-x5内核浏览器

    2020-07-06 13:52:38
    Android 集成x5内核浏览器demo
  • android腾讯X5内核集成

    2020-03-02 20:21:31
    官方给的Demo跑不通,在android9,oppo机型上几乎每次都失败,没办法下载x5内核,onViewInitFinished 回调都是false; 尝试从其他软件已下好x5.tbs org文件放到自己软件的目录下也不行,可能需要放到系统目录下...
  • Android集成腾讯X5WebView

    2018-10-10 11:22:31
    项目说明:最近在开发Android原生嵌套H5实现混合开发,刚开始采用原生的WebView各种兼容性问题,之后决定采用腾讯的x5浏览器来开发,遇到的一些问题列一下: - x5Webview与H5的交互问题 - x5同步cookie问题 -...
  • Android 腾讯 X5基础使用记录 。 腾讯 X5 是什么? 也是一个类似 WebView 的组件? 为什么不使用Android系统自带的WebView 而选择 腾讯的 X5? 相对于Android系统自带的WebView有一下有点:安全、极速,省流...
  • 安卓开发笔记(二十四):手把手教你一步步集成腾讯X5内核 1.为什么要集成腾讯 X5 浏览器内核 X5内核相对于系统webview,具有下述明显优势: 1) 速度快:相比系统webview的网页打开速度有30+%...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 制作好APP在真机上运行时发现页面总是略大于屏幕,查询网上的解决方法,通过Android原生webview设置分辨率啦、缩放啦、自适应等等,没啥用。后来看到X5WebView很多人赞,行吧,我也试试看好了。 走攻略下载X5...
  • 腾讯X5内核-android开发

    2020-06-19 23:07:09
    腾讯X5内核完整接入教程,并且提供完整示例。提供了Android Studio SDK接入方法,和Eclipse SDK接入方法。
  • 1、为什么要集成腾讯 X5 浏览器内核 肯定是事出有因,简单来说,JS代码写的不标准,与部分机型内嵌套的浏览器内核产生矛盾,出现底层(os)bug导致,不得不费事搞一个其它内核进行加载网页,具体原因。 2、官方...
1 2 3 4 5 ... 20
收藏数 9,201
精华内容 3,680