【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

目录
相关文章
|
2月前
|
Web App开发 iOS开发
Web 浏览器
【8月更文挑战第27天】Web 浏览器。
37 2
|
2月前
|
JSON API 数据处理
Winform管理系统新飞跃:无缝集成SqlSugar与Web API,实现数据云端同步的革新之路!
【8月更文挑战第3天】在企业应用开发中,常需将Winform桌面应用扩展至支持Web API调用,实现数据云端同步。本文通过实例展示如何在已有SqlSugar为基础的Winform系统中集成HTTP客户端调用Web API。采用.NET的`HttpClient`处理请求,支持异步操作。示例包括创建HTTP辅助类封装请求逻辑及在Winform界面调用API更新UI。此外,还讨论了跨域与安全性的处理策略。这种方法提高了系统的灵活性与扩展性,便于未来的技术演进。
172 2
|
4月前
|
前端开发 安全 数据库
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
Web架构&前后端分离站&Docker容器站&集成软件站&建站分配
187 1
|
2月前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
33 1
|
2月前
|
jenkins 持续交付 开发工具
"引爆效率革命!Docker+Jenkins+GIT+Tomcat:解锁持续集成魔法,一键部署Java Web应用的梦幻之旅!"
【8月更文挑战第9天】随着软件开发复杂度的增加,自动化变得至关重要。本文通过实例展示如何结合Docker、Jenkins、Git与Tomcat建立高效的持续集成(CI)流程。Docker确保应用环境一致性;Jenkins自动化处理构建、测试和部署;Git管理源代码版本;Tomcat部署Web应用。在Jenkins中配置Git插件并设置项目,集成Docker构建Tomcat应用镜像并运行容器。此外,通过自动化测试、代码质量检查、环境隔离和日志监控确保CI流程顺畅,从而显著提高开发效率和软件质量。
62 3
|
2月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
57 0
|
3月前
|
数据采集 数据安全/隐私保护
Kameleo指纹浏览器进阶使用:轻松集成IPXProxy海外代理IP
Kameleo是一款出色的指纹浏览器,它能够帮助用户实现隐身浏览。大家在进行网络抓取的时候总会碰到一些阻碍,而采取指纹浏览器可以提升网络抓取的效率,并且集成代理IP能增加一层防护,让数据采集更加全面,为制定营销策略提供更好的支持。那如何将Kameleo指纹浏览器与IPXProxy海外代理IP集成?
|
3月前
|
机器人 Shell 开发者
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
|
3月前
|
安全
全面掌握Dolphin指纹浏览器:IPXProxy代理IP集成使用指南
对于需要管理多个社交媒体或电商平台的用户而言,Dolphin指纹浏览器提供了便捷的多账号隔离功能,搭配代理IP可以有效的防止账户关联。并且Dolphin指纹浏览器能够支持团队协作,方便团队进行互动、跟踪账户、查看代理状态。一些刚接触指纹浏览器的用户,不知道如何将Dolphin指纹浏览器和代理IP集成使用,下面以IPXProxy代理IP为例,带来详细的操作步骤。
|
2月前
|
网络安全 数据安全/隐私保护 iOS开发
【Mac os】如何在服务器上启动Jupyter notebook并在本地浏览器Web端环境编辑程序
本文介绍了如何在服务器上启动Jupyter Notebook并通过SSH隧道在本地浏览器中访问和编辑程序的详细步骤,包括服务器端Jupyter的启动命令、本地终端的SSH隧道建立方法以及在浏览器中访问Jupyter Notebook的流程。
61 0
下一篇
无影云桌面