一.常用API
setBlockNetworkImage 是否显示网络图像
setBuiltInZoomControls 设置是否支持缩放
setCacheMode 设置缓冲的模式
setDefaultFontSize 设置默认的字体大小
setDefaultTextEncodingName 设置在解码时使用的默认编码
setFixedFontFamily 设置固定使用的字体
setJavaSciptEnabled 设置是否支持Javascript
setLayoutAlgorithm 设置布局方式
setLightTouchEnabled 设置用鼠标激活被选项
setSupportZoom 设置是否支持变焦
WebViewClient常用方法:
doUpdate VisitedHistory 更新历史记录
onFormResubmission 应用程序重新请求网页数据
onLoadResource 加载指定地址提供的资源
onPageFinished 网页加载完毕
onPageStarted 网页开始加载
onReceivedError 报告错误信息
onScaleChanged WebView发生改变
shouldOverrideUrlLoading 控制新的连接在当前WebView中打开
WebChromeClient常用方法:
onCloseWindow 关闭WebView
onCreateWindow 创建WebView
onJsAlert 处理Javascript中的Alert对话框
onJsConfirm处理Javascript中的Confirm对话框
onJsPrompt处理Javascript中的Prompt对话框
onProgressChanged 加载进度条改变
onReceivedlcon 网页图标更改
onReceivedTitle 网页Title更改
onRequestFocus WebView显示焦点
Setting是WebView提供给上层App的一个配置Webview的接口,每 一个WebView都有一个WebSettings,要控制WebView的行为,只有通过WebView.getSettigs()获取 WebSettings对象的引用,然后再改变它的属性。
二.webview滑动闪屏问题
那是因为webview背景的问题,在你当前 webview 的activity的manifest里面加这句话 android:hardwareAccelerated="false"然后再代码中设置:
webView.loadUrl(URL);
// 先设置背景色为tranaparent 透明色
webView.setBackgroundColor(0);
// 然后设置背景图片
webView.setBackgroundResource(R.drawable.background_book);
三.控制BACK键返回上级历史记录
这个onKeyDown(int, KeyEvent)回调方法将会在Activity中按钮被按下的时候调用。KeyEvent中的条件是核对按下的键是BACK键以及WebView可以 回退(它有历史记录)。如果条件满足,就会调用goBack()方法在WebView历史中回退一个步骤。返回true表明这个事件已经被处理了。如果条件不满足,这个事件就会被回送给系统。再次运行程序。你现在可以点击进入链接并能够在页面历史中回退了。
权限:
<uses-permission android:name="android.permission.INTERNET"/>
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
四.常用知识点:
1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
2.如果访问的页面中有Javascript,则webview必须设置支持Javascript。 webview.getSettings().setJavaScriptEnabled(true);
3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象并重写shouldOverrideUrlLoading方法。
webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } });
4.android中webview支持javascript自定义对象
a.设置webview支持javascript.webSettings.setJavaScriptEnabled(true);
b.绑定android对象到javascript对象. addJavascriptInterface(Object obj,String interfaceName);
c.页面中调用javascript对象. javascript:window.interfaceName.方法名称();
在w3c标准中js有 window,history,document等标准对象,同样我们可以在开发浏览器时自己定义我们的对象调用手机系统功能来处理,这样使用js就可以 为所欲为了。
public class WebViewDemo extends Activity {
private WebView mWebView;
private Handler mHandler = new Handler();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.webviewdemo);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new Object() {
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
mWebView.loadUrl("javascript:wave()");
}
});
}
}, "demo");
mWebView.loadUrl("file:///android_asset/demo.html");
}
}
五.WebView控制进度
创建WebChromeClient对象并重写onProgressChanged(WebView view, int progress)方法:
public class ProgressWebView extends WebView { private ProgressBar progressbar; public ProgressWebView(Context context) { super(context); progressbar = new ProgressBar(context, null,android.R.attr.progressBarStyleHorizontal); progressbar.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,10, 0, 0)); progressbar.setProgressDrawable(context.getResources().getDrawable( R.drawable.scrubber_progress_horizontal_holo_light)); addView(progressbar); setWebChromeClient(new WebChromeClient()); } public class WebChromeClient extends android.webkit.WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { progressbar.setVisibility(GONE); } else { if (progressbar.getVisibility() == GONE) progressbar.setVisibility(VISIBLE); progressbar.setProgress(newProgress); } super.onProgressChanged(view, newProgress); } } }
六.shouldOverrideUrlLoading
WebView wView =(WebView)findViewById(R.id.webview); wView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebViewview, String url) { // TODO Auto-generated method stub view.loadUrl(url); return true; });
WebView中的shouldOverrideUrlLoading和onPageStarted这两个方法就是可以捕获到跳转的url,然后进行一系列的操作,但是他们两到底有什么区别呢?
当点击页面中的链接的时候他们俩都会执行,但是返回到上一个页面的时候onPageStarted会执行,但是shouldOverrideUrlLoading就不执行了,就是onPageStarted什么时候都执行的,
应用场景:有个需求WebView加载不同的url的时候应用的标题也是跟着改变的,这时候只要在onPageStarted中捕获url前缀进行 判断就可以了,但是不能使用shouldOverrideUrlLoading,因为当从当前的页面返回到上个页面的时候这个方法并不执行,所以捕获就没有用了!
七.网页缓存
1、缓存构成
/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db
2.缓存模式(5种)
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
如:www.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时 才从网络上获取。
www.360.com.cn的cache-control为max-age=60,在两种模式下都使用本地缓存数据。
总结:根据以上两种模式,建议缓存策略为,判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。
3.设置WebView 缓存模式
private void initWebView() {
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); // 设置缓存模式
// 开启 DOM storage API 功能
mWebView.getSettings().setDomStorageEnabled(true);
// 开启 database storage API 功能
mWebView.getSettings().setDatabaseEnabled(true);
String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
// String cacheDirPath =
// getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME;
Log.i(TAG, "cacheDirPath=" + cacheDirPath);
// 设置数据库缓存路径
mWebView.getSettings().setDatabasePath(cacheDirPath);
// 设置 Application Caches 缓存目录
mWebView.getSettings().setAppCachePath(cacheDirPath);
// 开启 Application Caches 功能
mWebView.getSettings().setAppCacheEnabled(true);
}
八.WebView中Header与Cookie/** * 清除WebView缓存 **/ public void clearWebViewCache(){ //清理Webview缓存数据库 (Context对象方法) try { deleteDatabase("webview.db"); deleteDatabase("webviewCache.db"); } catch (Exception e) { e.printStackTrace(); } //WebView 缓存文件 File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache"); Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath()); //删除webview 缓存目录 if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir); } //删除webview 缓存 缓存目录 if(appCacheDir.exists()){ deleteFile(appCacheDir); } } /** * 清除WebView缓存 **/ public void clearWebViewCache(){ //清理Webview缓存数据库 (Context对象方法) try { deleteDatabase("webview.db"); deleteDatabase("webviewCache.db"); } catch (Exception e) { e.printStackTrace(); } //WebView 缓存文件 File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache"); Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath()); //删除webview 缓存目录 if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir); } //删除webview 缓存 缓存目录 if(appCacheDir.exists()){ deleteFile(appCacheDir); } } /** * 递归删除 文件/文件夹 * * @param file */ public void deleteFile(File file) { Log.i(TAG, "delete file path=" + file.getAbsolutePath()); if (file.exists()) { if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { File files[] = file.listFiles(); for (int i = 0; i < files.length; i++) { deleteFile(files[i]); } } file.delete(); } else { Log.e(TAG, "delete file no exists " + file.getAbsolutePath()); } } }
1.这里说的cookie不是传统意义上的cookie,传统来讲cookie是服务器保存在客户端的信息,以便下次请求时能够通过读取cookie识别客户端身份等信息。2.Cookie发送也是放在header中发送的。
3.android.webkit.CookieManager是android cookie的管理类,可以讲客户端信息封装在cookiemanager中,这样系统发送请求时就自动带上这些cookie信息。
4.在Android手机中,Cookie的相关信息保存在/data/data/package_name/database/webview.db中.
WebView cookies清理:
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
CookieManager.getInstance().removeSessionCookie();
另外,清理cache 和历史记录的方法:
WebView.clearCache(true);
WebView.clearHistory();当我们加载Html时候,会在我们data/应用package下生成database与cache两个文件夹:
我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webviewCache文件夹下.
WebView中存在着两种缓存:网页数据缓存(存储打开过的页面及资源)、H5缓存(即AppCache)。
综合可以得知 webview 会将我们浏览过的网页url已经网页文件(css、图片、js等)保存到数据库表中
根据setAppCachePath(String appCachePath)提供的路径,在H5使用缓存过程中生成的缓存文件。
2、缓存模式
无模式选择,通过setAppCacheEnabled(boolean flag)设置是否打开。默认关闭,即,HTML5的缓存无法使用。3、清除缓存
找到调用setAppCachePath(String appCachePath)设置缓存的路径,把它下面的文件全部删除就OK了。4、控制大小
通过setAppCacheMaxSize(long appCacheMaxSize)设置缓存最大容量,默认为Max Integer。十.处理WebView中的非超链接请求(如Ajax请求):有时候需要加上请求头,但是非超链接的请求,没有办法再shouldOverrinding中拦截并用webView.loadUrl(String url,HashMap headers)方法添加请求头
目前用了一个临时的办法解决:
首先需要在url中加特殊标记/协议, 如在onWebViewResource方法中拦截对应的请求,然后将要添加的请求头,以get形式拼接到url末尾
在shouldInterceptRequest()方法中,可以拦截到所有的网页中资源请求,比如加载JS,图片以及Ajax请求等等
@SuppressLint("NewApi")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view,String url) {
// 非超链接(如Ajax)请求无法直接添加请求头,现拼接到url末尾,这里拼接一个imei作为示例
String ajaxUrl = url;
// 如标识:req=ajax
if (url.contains("req=ajax")) {
ajaxUrl += "&imei=" + imei;
}
return super.shouldInterceptRequest(view, ajaxUrl);
}
十一.杂七杂八的显示问题
1.在页面中先显示图片:
@Override
public void onLoadResource(WebView view, String url) {
mEventListener.onWebViewEvent(CustomWebView.this, OnWebViewEventListener.EVENT_ON_LOAD_RESOURCE, url);
if (url.indexOf(".jpg") > 0) {
hideProgress(); //请求图片时即显示页面
mEventListener.onWebViewEvent(CustomWebView.this, OnWebViewEventListener.EVENT_ON_HIDE_PROGRESS, view.getUrl());
}
super.onLoadResource(view, url);
}
2.屏蔽掉长按事件 因为webview长按时将会调用系统的复制控件:
mWebView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return true;
}
});
3.在WebView加入 flash支持:
String temp = "<html><body bgcolor=\"" + "black"
+ "\"> <br/><embed src=\"" + url + "\" width=\"" + "100%"
+ "\" height=\"" + "90%" + "\" scale=\"" + "noscale"
+ "\" type=\"" + "application/x-shockwave-flash"
+ "\"> </embed></body></html>";
String mimeType = "text/html";
String encoding = "utf-8";
web.loadDataWithBaseURL("null", temp, mimeType, encoding, "");
4.WebView保留缩放功能但隐藏缩放控件:
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
if (DeviceUtils.hasHoneycomb())
mWebView.getSettings().setDisplayZoomControls(false);
注意:setDisplayZoomControls是在Android 3.0中新增的API.
5.WebView加载Html右边空白问题的解决方案
1.在layout的xml文件中,WebView组件的元素中添加:android:scrollbars="none"属性;
如:<WebView android:id="@+id/myWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none"/>2.在Activity类中,取到WebView对象,添加myWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
如:WebView myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
6.使用WebView// 优化private void setDefaultView() {ProgressWebView webview = new ProgressWebView(this);WebSettings ws = webview.getSettings();ws.setJavaScriptEnabled(false);ws.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);ws.setLoadWithOverviewMode(true);DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);int mDensity = metrics.densityDpi;if (mDensity == 120) {ws.setDefaultZoom(ZoomDensity.CLOSE);} else if (mDensity == 160) {ws.setDefaultZoom(ZoomDensity.MEDIUM);} else if (mDensity == 240) {ws.setDefaultZoom(ZoomDensity.FAR);}webview.loadUrl(url);webview.setDownloadListener(new MyWebViewDownLoadListener());webview.setWebViewClient(new MyWebViewClient());setContentView(webview);}// 不优化private void setView2() {ProgressWebView webview = new ProgressWebView(this);WebSettings ws = webview.getSettings();ws.setJavaScriptEnabled(true);ws.setSupportZoom(true);webview.loadUrl(url);webview.setDownloadListener(new MyWebViewDownLoadListener());webview.setWebViewClient(new MyWebViewClient());setContentView(webview);}7.处理下载链接private class MyWebViewDownLoadListener implements DownloadListener {@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype,long contentLength) {Uri uri = Uri.parse(url);Intent intent = new Intent(Intent.ACTION_VIEW, uri);startActivity(intent);}} 8.设置缩放网页mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);9.图片过大导致左右滑动
settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true);
10.Android判断WebView是否已经滚动到页面底端:
getScrollY()方法返回的是当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离.
getHeight()或者getBottom()方法都返回当前WebView 这个容器的高度
getContentHeight 返回的是整个html 的高度,但并不等同于当前整个页面的高度,因为WebView 有缩放功能,
所以当前整个页面的高度实际上应该是原始html 的高度再乘上缩放比例.
因此,更正后的结果,准确的判断方法应该是:
if(WebView.getContentHeight*WebView.getScale() == (webview.getHeight()+WebView.getScrollY())){
//已经处于底端
}