WebView填坑之旅1--腾讯x5内核(tbs)

###序
说到webView大家可能都熟悉,基本每个android开发都用过吧,开始觉得这玩意没什么特别的,不就把url往webView一丢,网页就可以加载了吗?哈哈哈
事实上…这玩意套路还挺多的,我在开发过程中也是遇到各种问题,一般也是解决这个问题,又出现新的问题,好在,现在项目中webView相关的东西基本都完善了,最近也稍微空闲一点,把项目中遇到过的一些问题分享一下,也权当记录,有什么不对的,希望大家多多指教=. =

###腾讯x5内核(tbs)
这玩意大家应该都知道吧,微信、QQ的网页加载都是这货,他的优势呢,不言自明,我项目中开始是用的原生webView,但原生的并不是那么完美,后面就用到了x5内核的webView,到现在出现过一次问题,就是应用宝的下载页,一直不显示下载按钮,这个问题是由于手机中微信x5内核的影响(那一阵微信正好更新),其他的呢都挺好的,比如页面内键盘弹出的处理、访问不到url的错误页面的处理等等

首先接入x5吧 官网

然后,继承x5的webview,把一些通用的设置封装起来(注意相关导包不要用原生的)

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

import com.orhanobut.logger.Logger;
import com.tencent.smtt.sdk.DownloadListener;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;

/**
 * 封装x5内核的webView
 * Created by ly on 2017/9/8 20:16
 */
public class X5WebView extends WebView {

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

    public X5WebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

        init();
    }

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

    @SuppressLint("SetJavaScriptEnabled")
    private void init() {
        Logger.d(">>>>>>>>X5WebView init");
        // WebStorage webStorage = WebStorage.getInstance();
        this.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        this.getView().setClickable(true);

        initWebViewSettings();
    }

    private void initWebViewSettings() {
        WebSettings webSetting = this.getSettings();
        webSetting.setNavDump(true);
        webSetting.setJavaScriptEnabled(true);
        webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
        webSetting.setAllowFileAccess(true);
        //把所有内容放在webview等宽的一列中,从而实现适应屏幕(可能会出现页面中链接失效)
        //webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setUseWideViewPort(true);
        webSetting.setLoadWithOverviewMode(true);
        webSetting.setBuiltInZoomControls(true);
        //要打开新窗口时onCreateWindow会调用
        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);

        //关闭webView组件的保存密码功能
        webSetting.setSavePassword(false);
        webSetting.setSaveFormData(false);

		//this.getSettingsExtension()
		//    .setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
    }

    public void setWebViewClient(WebViewClient webViewClient) {
        super.setWebViewClient(webViewClient);
    }

    public void setWebChromeClient(WebChromeClient webChromeClient) {
        super.setWebChromeClient(webChromeClient);
    }

    public void setDownloadListener(DownloadListener downloadListener) {
        super.setDownloadListener(downloadListener);
    }

###定义基类webActivity
接着是定义通用的webActivity基类,毕竟我们是要为了方便使用及维护
其实呢,这个BaseWebActivity 还可以弄成abstract的,从子类传入布局及标题这些东西,那样会更好,有时间再整理
里面有一些标题设置相关的东西,忽略即可…

/**
 * web界面基类
 * Created by ly on 2017/8/24 10:09.
 */
public class BaseWebActivity extends BaseActivity {

    private X5WebView wv;
    private CustomWebChromeClient webChromeClient;
    private SmoothProgressBar pb_web;
    private String url, title;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        url = intent.getStringExtra(Constants.INTENT_KEY_URL);
        title = intent.getStringExtra(Constants.INTENT_KEY_TITLE);
        Logger.i("传入的url:" + url);
//        if (TextUtils.isEmpty(url)) {
//            finish();
//            return;
//        }

        //url = "http://a.app.qq.com/o/simple.jsp?pkgname=com.lianchuan.kaledai";
        //测试文件选择
        //url = "file:///android_asset/webpage/fileChooser.html";

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        //解决网页中的视频,上屏幕的时候,可能出现闪烁的情况
        getWindow().setFormat(PixelFormat.TRANSLUCENT);

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

        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                getWindow().setFlags(android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                        android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        initWebView();
    }

    @Override
    public void setContentView(View view) {
        super.setContentView(view);
        initWebView();
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        super.setContentView(view, params);
        initWebView();
    }

    private void initWebView() {

        topTitleBar.setTitleText(title);
        topTitleBar.setShowRightButton(false);

        wv = (X5WebView) findViewById(R.id.web_view);
        pb_web = (SmoothProgressBar) findViewById(R.id.pb_web);

        webChromeClient = new CustomWebChromeClient(this);
        wv.setWebChromeClient(webChromeClient);
        wv.setWebViewClient(new CustomWebViewClient(wv, pb_web));
        wv.setDownloadListener(new CustomDownloadListener(this));

        wv.loadUrl(url);

        AndroidBug5497Workaround.assistActivity(this);
    }

    public WebView getWebView() {
        return wv;
    }

    /**
     * 设置页面标题
     *
     * @param title 网页中解析的标题
     *              Created by ly on 2017/9/26 9:51
     */
    public void setTopTitle(String title) {
        if (TextUtils.isEmpty(title)) {
            if (topTitleBar != null)
                topTitleBar.setTitleText(this.title);
        } else {
            if (topTitleBar != null)
                topTitleBar.setTitleText(title);
        }
    }

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

        //从web页选择文件/拍照的处理
        if (requestCode == CustomWebChromeClient.FILECHOOSER_CHOOSERFILE
                || requestCode == CustomWebChromeClient.FILECHOOSER_TAKEPICTURE) {
            Uri result;
            if (requestCode == CustomWebChromeClient.FILECHOOSER_CHOOSERFILE) {
                result = data == null ? null : data.getData();
            } else {
                result = CommonUtils.getUriForFile(webChromeClient.getTakePicFile());
            }

            ValueCallback uploadFile = webChromeClient.getUploadFile();
            ValueCallback uploadFiles = webChromeClient.getUploadFiles();
            if (null != uploadFile) {
                uploadFile.onReceiveValue(result);
                webChromeClient.setUploadFile(null);
            }
            if (null != uploadFiles) {
                uploadFiles.onReceiveValue(result == null ? null : new Uri[]{result});
                webChromeClient.setUploadFiles(null);
            }
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (wv != null && wv.canGoBack()) {
                wv.goBack();
                return true;
            } else
                return super.onKeyDown(keyCode, event);
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (wv != null) {
            ((ViewGroup) findViewById(R.id.ll_web)).removeView(wv);
            wv.removeAllViews();
            wv.destroy();
            wv = null;
        }
        if (pb_web != null)
            pb_web.release();
        if (webChromeClient != null) {
            webChromeClient.setUploadFile(null);
            webChromeClient.setUploadFiles(null);
        }
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

需要用到web页面的时候,写一个activity继承BaseWebActivity 即可,像这样:

/**
 * Created by ly on 2017/8/24 14:45.
 */
public class CommWebActivity extends BaseWebActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_common_web);

        //在js中调用本地java方法
        getWebView().addJavascriptInterface(new JsInterface(this), "xx");
    }
}

好了,这一篇主要就是这些了,一些基础的搭建

你可能感兴趣的:(android)