【Android Web】腾讯X5浏览器的集成与常见问题

简介: 近年来,混合开发也越来越用的更多,而原生webview的各种坑,比如说 上传图片、文件问题、视频全屏问题(什么在微信上打开都是好的,你这怎么全屏不了)、版本差异问题,所以还是建议使用腾讯x5浏览器。

近年来,混合开发也越来越用的更多,而原生webview的各种坑,比如说 上传图片、文件问题、视频全屏问题(什么在微信上打开都是好的,你这怎么全屏不了)、版本差异问题,所以还是建议使用腾讯x5浏览器。

废话不多说,我们开始集成吧

1.去官网上下载最新的jar、so文件等 链接点这里

2.添加jar包、so文件,配置gradle

img_286fa973378a7f1694e77c837839b3b0.png
QQ截图20180728102235.png

在build.gradle 中添加libs、配置ndk

 sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
  ndk {
            abiFilters "armeabi"
        }

3.在Application中添加初始化x5代码,记得在AndroidManifest.xml中注册你自定的Application

  QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

            @Override
            public void onViewInitFinished(boolean arg0) {
                //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
                Log.d("app", " onViewInitFinished is " + arg0);
            }

            @Override
            public void onCoreInitFinished() {
            }
        };
        //x5内核初始化接口
        QbSdk.initX5Environment(getApplicationContext(), cb);

4.添加权限


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

5.添加WebActivity,初始化x5配置 记得在AndroidManifest.xml中注册

        webView = (WebView) findViewById(R.id.webView);
        WebSettings webSetting = webView.getSettings();
        webSetting.setJavaScriptEnabled(true);
        webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
        webSetting.setAllowFileAccess(true);
        webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setBuiltInZoomControls(false);
        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);

        getWindow().setFormat(PixelFormat.TRANSLUCENT);

        webView.getView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);

        // this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
        // settings 的设计
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
                webView.loadUrl(url);
                return true;
            }
        });

添加上传文件、图片适配代码

  webView.setWebChromeClient(new WebChromeClient() {


            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android < 3.0
            public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  > 4.1.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  >= 5.0
            public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                             ValueCallback<Uri[]> filePathCallback,
                                             WebChromeClient.FileChooserParams fileChooserParams) {
                uploadFiles = filePathCallback;
                openFileChooseProcess();
                return true;
            }

        });

    private void openFileChooseProcess() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("*/*");
        startActivityForResult(Intent.createChooser(i, "test"), 0);
    }

处理选择文件、图片后回调

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case 0:
                    if (null != uploadFile) {
                        Uri result = data == null || resultCode != RESULT_OK ? null
                                : data.getData();
                        uploadFile.onReceiveValue(result);
                        uploadFile = null;
                    }
                    if (null != uploadFiles) {
                        Uri result = data == null || resultCode != RESULT_OK ? null
                                : data.getData();
                        uploadFiles.onReceiveValue(new Uri[]{result});
                        uploadFiles = null;
                    }
                    break;
                default:
                    break;
            }
        } else if (resultCode == RESULT_CANCELED) {
            if (null != uploadFile) {
                uploadFile.onReceiveValue(null);
                uploadFile = null;
            }

        }
    }

添加视频全屏相关代码


        webView.setWebChromeClient(new WebChromeClient() {


            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android < 3.0
            public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  > 4.1.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  >= 5.0
            public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                             ValueCallback<Uri[]> filePathCallback,
                                             WebChromeClient.FileChooserParams fileChooserParams) {
                uploadFiles = filePathCallback;
                openFileChooseProcess();
                return true;
            }

            View myVideoView;
            View myNormalView;
            IX5WebChromeClient.CustomViewCallback callback;


            /**
             * 全屏播放配置
             */
            @Override
            public void onShowCustomView(View view,
                                         IX5WebChromeClient.CustomViewCallback customViewCallback) {
                FrameLayout normalView = (FrameLayout) findViewById(R.id.web_filechooser);
                ViewGroup viewGroup = (ViewGroup) normalView.getParent();
                viewGroup.removeView(normalView);
                viewGroup.addView(view);
                myVideoView = view;
                myNormalView = normalView;
                callback = customViewCallback;
            }

            @Override
            public void onHideCustomView() {
                if (callback != null) {
                    callback.onCustomViewHidden();
                    callback = null;
                }
                if (myVideoView != null) {
                    ViewGroup viewGroup = (ViewGroup) myVideoView.getParent();
                    viewGroup.removeView(myVideoView);
                    viewGroup.addView(myNormalView);
                }
            }

        });
 webView.addJavascriptInterface(new WebViewJavaScriptFunction() {

            @Override
            public void onJsFunctionCalled(String tag) {

            }

            @JavascriptInterface
            public void onX5ButtonClicked() {
                enableX5FullscreenFunc();
            }

            @JavascriptInterface
            public void onCustomButtonClicked() {
                disableX5FullscreenFunc();
            }

            @JavascriptInterface
            public void onLiteWndButtonClicked() {
                enableLiteWndFunc();
            }

            @JavascriptInterface
            public void onPageVideoClicked() {
                enablePageVideoFunc();
            }
        }, "Android");
  // 向webview发出信息
    private void enableX5FullscreenFunc() {

        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示标准全屏,false表示X5全屏;不设置默认false,

            data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,

            data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void disableX5FullscreenFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", true);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,

            data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,

            data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void enableLiteWndFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,

            data.putBoolean("supportLiteWnd", true);// false:关闭小窗;true:开启小窗;不设置默认true,

            data.putInt("DefaultVideoScreen", 2);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void enablePageVideoFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示标准全屏,会调起onShowCustomView(),false表示X5全屏;不设置默认false,

            data.putBoolean("supportLiteWnd", false);// false:关闭小窗;true:开启小窗;不设置默认true,

            data.putInt("DefaultVideoScreen", 1);// 1:以页面内开始播放,2:以全屏开始播放;不设置默认:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

添加下载相关代码

 webView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String s, String s1, String s2, String s3, long l) {

            }
        });

最后,当Activity销毁时,释放webview

 /**
     * 确保注销配置能够被释放
     */
    @Override
    protected void onDestroy() {
        if (this.webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }

到这里,x5浏览器的集成已经完成了,快去试试吧

常见问题

1.视频无法全屏

请注意AndroidManifest.xml 中配置

 <activity
            android:name=".WebActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"></activity>

2.原生与webview 共享cookie

首先,原生需要将cookie 持久化的保存起来,具体可以参考 【Android架构】基于MVP模式的Retrofit2+RXjava封装之常见问题(四),至于非okhttp网络的,可以自行百度
然后传递给webview

      //创建CookieSyncManager
        CookieSyncManager.createInstance(context);
        //得到CookieManager
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeSessionCookie();// 移除
        cookieManager.removeAllCookie();
        //得到向URL中添加的Cookie的值
        store = new PersistentCookieStore(context);
        List<Cookie> cookieList = store.getCookies();
        if (cookieList != null && cookieList.size() > 0) {
            Cookie cookie = null;
         for (Cookie c : cookieList) {
                if (c.domain() != null) {
                    if (c.domain().contains("38")) {
                        cookie = c;
                    }
                }
            }
            if (cookie == null) {
                cookie = cookieList.get(0);
            }


            cookieManager.setCookie(url, cookie.name() + "=" + cookie.value());
          if (Build.VERSION.SDK_INT < 21) {
                CookieSyncManager.getInstance().sync();
            } else {
                CookieManager.getInstance().flush();
            }
        }

需要注意的是,本地保存的cookie可能会有多个,要根据domain 来判断出正确的cookie

目录
相关文章
|
5天前
|
数据采集 前端开发 项目管理
ClkLog常见问题-埋点集成篇Sec. 2
本篇将继续解答ClkLog使用过程中【埋点集成】阶段的常见问题。
|
5月前
|
前端开发 安全 数据库
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
198 1
|
22天前
|
Web App开发 Android开发
利用firefox调试安卓手机端web
该教程详细介绍如何通过Firefox浏览器实现手机与电脑的远程调试。手机端需安装最新版Firefox,并按指定步骤设置完成;电脑端则需安装15版及以上Firefox。设置完成后,通过工具栏中的“远程调试”选项,输入手机IP地址即可连接。连接确认后,即可使用电脑端Firefox调试器调试手机上的Web信息。注意,调试前手机需提前打开目标网页。
36 2
|
22天前
|
Web App开发 XML JavaScript
Python 操作浏览器:让 Python 和 Web 世界合二为一
Python 操作浏览器:让 Python 和 Web 世界合二为一
30 3
|
13天前
|
搜索推荐 JavaScript BI
ClkLog常见问题-埋点集成篇Sec. 1
本篇主要解答ClkLog使用过程中【埋点集成】阶段的常见问题。
|
3月前
|
存储 消息中间件 前端开发
Web2py框架下的神秘力量:如何轻松集成第三方API,让你的应用不再孤单!
【8月更文挑战第31天】在开发现代Web应用时,常需集成第三方服务如支付网关、数据存储等。本文将指导你使用Web2py框架无缝接入第三方API。通过实例演示从注册获取API密钥、创建控制器、发送HTTP请求到处理响应的全过程。利用`requests`库与Web2py的内置功能,轻松实现API交互。文章详细介绍了如何编写RESTful控制器,处理API请求及响应,确保数据安全传输。通过本教程,你将学会如何高效整合第三方服务,拓展应用功能。欢迎留言交流心得与建议。
46 1
|
3月前
|
Android开发 iOS开发
[ionic]解决运行Android、IOS出现Could not find the web assets directory
[ionic]解决运行Android、IOS出现Could not find the web assets directory
33 1
|
3月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
119 0
|
3月前
|
Java 数据库连接 数据库
强强联手!JSF 与 Hibernate 打造高效数据访问层,让你的应用如虎添翼,性能飙升!
【8月更文挑战第31天】本文通过具体示例详细介绍了如何在 JavaServer Faces (JSF) 应用程序中集成 Hibernate,实现数据访问层的最佳实践。首先,创建一个 JSF 项目并在 Eclipse 中配置支持 JSF 的服务器版本。接着,添加 JSF 和 Hibernate 依赖,并配置数据库连接池和 Hibernate 配置文件。然后,定义实体类 `User` 和 DAO 类 `UserDAO` 处理数据库操作。
57 0
|
3月前
|
iOS开发 Android开发 MacOS
从零到全能开发者:解锁Uno Platform,一键跨越多平台应用开发的神奇之旅,让你的代码飞遍Windows、iOS、Android、macOS及Web,技术小白也能秒变跨平台大神!
【8月更文挑战第31天】从零开始,踏上使用Uno Platform开发跨平台应用的旅程。只需编写一次代码,即可轻松部署到Windows、iOS、macOS、Android及Web(通过WASM)等多个平台。Uno Platform为.NET生态带来前所未有的灵活性和效率,简化跨平台开发。首先确保安装了Visual Studio或VS Code及.NET SDK,然后选择合适的项目模板创建新项目。项目结构类似传统.NET MAUI或WPF项目,包含核心NuGet包。通过简单的按钮示例,你可以快速上手并构建应用。Uno Platform让你的技术探索之旅充满无限可能。
56 0