• home > webfront > browser > x5 >

    H5混合开发优化:用鹅厂的X5内核替代webview—逐步舍弃cordova

    Author:zhoulujun Date:

    其实我觉得这个并没有什么好讲的。选用x5无非就是用下别人轮子。植入也很简单。关键是我们如何打通APP与前端也能的交互能力。这就涉及webview与JavaScript的通信问题。 在Android端,一是拦截url与弹窗拦截,二是@addJavascriptInterfa

    自己纯手工改造WebView,从下载到编译代价太大。且优化方面,对自己的信心都不是很大。

    所以也就拿着轮子用,如X5。选用X5是因为微信qq等都是用它,那就随大众。

    下载https://x5.tencent.com/tbs/sdk.html,并在其官网申请密钥,然后看官文档:https://x5.tencent.com/tbs/guide/sdkInit.html

    操作一通,可以跑起,但是,这个文档,真的是很鹅厂啊。

    需要配置的权限大致如下:

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

    将layout中的webView替换成X5webView。注意:这里的X5webView是需要带路径的,如com.X5util.X5WebView

    <X5WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbarSize="3dp" />

    在mainActivity或者application中加载X5内核(建议在application中加载)

    其实关于这方面,我觉得这篇文章《x5开源库后续知识点》写的很详细的了,这里摘要一点重点

    WebView.loadUrl(url)流程

    开始执行页面加载操作时,会回调WebViewClient.onPageStarted(webview,url,favicon)

    加载页面的过程中回调 

    • WebChromeClient.onReceivedTitle(webview, title),用来设置标题。需要注意的是,在部分Android系统版本中可能会回调多次这个方法,而且有时候回调的title是一个url,客户端可以针对这种情况进行特殊处理,避免在标题栏显示不必要的链接。

    • WebChromeClient.onProgressChanged(webview, progress),根据这个回调,可以控制进度条的进度(包括显示与隐藏)。一般情况下,想要达到100%的进度需要的时间较长(特别是首次加载),用户长时间等待进度条不消失必定会感到焦虑,影响体验。其实当progress达到80的时候,加载出来的页面已经基本可用了。事实上,国内厂商大部分都会提前隐藏进度条,让用户以为网页加载很快。

    • WebViewClient.shouldInterceptRequest(webview, request),无论是普通的页面请求(使用GET/POST),还是页面中的异步请求,或者页面中的资源请求,都会回调这个方法,给开发一次拦截请求的机会。在这个方法中,我们可以进行静态资源的拦截并使用缓存数据代替,也可以拦截页面,使用自己的网络框架来请求数据。包括后面介绍的WebView免流方案,也和此方法有关。

    • WebViewClient.shouldOverrideUrlLoading(webview, request),如果遇到了重定向,或者点击了页面中的a标签实现页面跳转,那么会回调这个方法。可以说这个是WebView里面最重要的回调之一,后面WebView与Native页面交互一节将会详细介绍这个方法。

    • WebViewClient.onReceivedError(webview,handler,error),加载页面的过程中发生了错误,会回调这个方法。主要是http错误以及ssl错误。在这两个回调中,我们可以进行异常上报,监控异常页面、过期页面,及时反馈给运营或前端修改。在处理ssl错误时,遇到不信任的证书可以进行特殊处理,例如对域名进行判断,针对自己公司的域名“放行”,防止进入丑陋的错误证书页面。也可以与Chrome一样,弹出ssl证书疑问弹窗,给用户选择的余地。

    加载页面结束回调WebViewClient.onPageFinished(webview,url)。这时候可以根据回退栈的情况判断是否显示关闭WebView按钮。通过mActivityWeb.canGoBackOrForward(-1)判断是否可以回退。

    js的调用时机分析

    做过WebView开发,并且需要和js交互,什么调用js呢

    • WebViewClient.onPageFinished():官方建议把js注入的时机放在页面开始加载之后,即在WebViewClient.onPageFinished()方法中注入最合适,。此时dom树已经构建完成,页面已经完全展现出来。但如果做过页面加载速度的测试,会发现WebViewClient.onPageFinished()方法通常需要等待很久才会回调(首次加载通常超过3s),这是因为WebView需要加载完一个网页里主文档和所有的资源才会回调这个方法。

    • WebViewClient.onPageStarted(),兼容性不好

    • WebViewClient.onProgressChanged():则需要避免重复注入,需要增强逻辑。

    Android调用Js

    需要设置webView.setJavaScriptEnabled(true)

    1. webView.loadUrl("javascript:showData(" + result + ")"),native 调用 js 的方法,但是获取返回的值比较麻烦

    2. webView.evaluateJavascript(jsStr, new ValueCallback<String>(): 4.4 版本引入的,所以局限性比较大。

    Js调用Android

    需要设置:webView.getSettings().setJavaScriptEnabled(true);

    1. 利用 WebViewClient 接口回调方法拦截 url: document.location = "js://openActivity?arg1=111&arg2=222";在Android拦截,public boolean shouldOverrideUrlLoading (WebView view, WebResourceRequest request)) 

      这种方式存在漏洞风险,如果 web 端想要得到方法的返回值,只能通过 WebView 的 loadUrl 方法去执行 JS 方法把返回值传递回去

    2. 利用 WebChromeClient 回调接口的三个方法(onJsAlert/onJsConfirm/onJsPrompt)拦截消息,prompt("js://openActivity?arg1=111&arg2=222");

       onJsAlert 是不能返回值的,而 onJsConfirm 只能够返回确定或者取消两个值,只有 onJsPrompt 方法是可以返回字符串类型的值

    3. @addJavascriptInterface 约束注解,前端与APP开发约定API即参数交互。、

    public class JSObject {
        private Context mContext;
        public JSObject(Context context) {
            mContext = context;
        }
        @JavascriptInterface
        public String showToast(String text) {
            Toast.show(mContext, text, Toast.LENGTH_SHORT).show();
            return "success";
        }
        @JavascriptInterface
        public void imageClick(String src) {
            Log.e("imageClick", "----点击了图片");
        }
    }

    是推荐@addJavascriptInterface 约束注解 近些接口开发



    转载本站文章《H5混合开发优化:用鹅厂的X5内核替代webview—逐步舍弃cordova》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/browser/x5/2020_0218_8314.html

    下一篇:Last page