Android WebView使用经验总结

接触WebView这么久,也积累了不少相关知识点,今天跟大家分享一下,希望对大家有帮助。

一.常用API
setAllowFileAccess 启用或禁止WebView访问文件数据

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;
       });
shouldOverrideUrlLoading并不是每次都在onPageStarted之前开始调用的,就是说一个新的URL不是每次都经过shouldOverrideUrlLoading的,只有在调用webview.loadURL的时候才会调用。
设置loadUrl时候是用哪个浏览器来加载。
shouldOverrideUrlLoading和onPageStarted方法的区别
     
     

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);
	}
 
 

4.清除缓存
/** 
     * 清除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());  
        }  
    }  
}  
.WebView中Header与Cookie        
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等)保存到数据库表中

九、HTML5缓存
1、缓存构成
根据setAppCachePath(String appCachePath)提供的路径,在H5使用缓存过程中生成的缓存文件。

2、缓存模式

无模式选择,通过setAppCacheEnabled(boolean flag)设置是否打开。默认关闭,即,HTML5的缓存无法使用。

3、清除缓存

找到调用setAppCachePath(String appCachePath)设置缓存的路径,把它下面的文件全部删除就OK了。

4、控制大小

通过setAppCacheMaxSize(long appCacheMaxSize)设置缓存最大容量,默认为Max Integer。

同时,可能通过覆盖WebChromeClient.onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)来设置缓存超过先前设置的最大容量时的策略。

 十.处理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 {
   
  @Override
 public 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())){
           //已经处于底端
         } 
 
   
 
   
11.loadData乱码问题解决方法
wv.getSettings().setDefaultTextEncodingName("UTF -8") ;
android webview loadData写成
loadData(data, "text/html; charset=UTF-8", null);
 
 
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值