###序
说到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");
}
}
好了,这一篇主要就是这些了,一些基础的搭建