您好,欢迎来到年旅网。
搜索
您的当前位置:首页Android中WebView的基本配置与填坑记录大全

Android中WebView的基本配置与填坑记录大全

来源:年旅网
Android中WebView的基本配置与填坑记录⼤全

前⾔

在应⽤程序开发过程中,经常会采⽤webview来展现某些界⾯,这样就可以不受发布版本控制,实时更新,遇到问题可以快速修复。

但是在Android开发中,由于Android版本分化严重,每⼀个版本针对webview都有部分更改,因此在开发过程中会遇到各种各样的坑,下⾯这篇就来给⼤家介绍关于Android中WebView的基本配置与填坑记录,话不多说了,来⼀起看看详细的介绍吧。基本配置

// 硬件加速

getActivity().getWindow().setFlags(

WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);// WebView 配置

WebSettings webSettings = mWebView.getSettings();// ⽣命周期

mWebView.onPause(); // 通过 onPause 动作通知内核暂停所有的动作,如 DOM 的解析、plugin 的执⾏、JavaScript 执⾏等mWebView.onResume(); // 恢复 WebView,能正常执⾏⽹页的响应((ViewGroup) mWebView.getParent()).removeView(mWebView);

mWebView.destroy(); // 当 Activity 要 destroy 时,应先将 WebView 移除,再 destroy 掉// 前进后退

if (mWebView.canGoBack()) { mWebView.goBack();}

if (mWebView.canGoForward()) { mWebView.goForward();}

// 缓存相关

mWebView.clearCache(true); // 清除缓存mWebView.clearHistory(); // 清除历史

mWebView.clearFormData(); // 清除表单数据

webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);// 设置缓存模式// 缓存模式

LOAD_DEFAULT: 默认,根据 cache-control 决定是否从⽹络上取数据

LOAD_NORMAL: API level 17 中已经废弃, 从API level 11开始作⽤同 LOAD_DEFAULT 模式

LOAD_CACHE_ELSE_NETWORK: 只要本地有,⽆论是否过期,或者 no-cache,都使⽤缓存中的数据LOAD_NO_CACHE: 不使⽤缓存,只从⽹络获取数据

LOAD_CACHE_ONLY: 不使⽤⽹络,只读取本地缓存数据// js 相关

webSettings.setJavaScriptEnabled(true); // ⽀持 js。如果碰到后台⽆法释放 js 导致耗电,应在 onStop 和 onResume ⾥分别设成 false 和 true mWebView.addJavascriptInterface(new WebAppInterface(this), \"android\"); // js 接⼝webSettings.setPluginsEnabled(true); // ⽀持插件// 设置⾃适应屏幕,两者合⽤

webSettings.setUseWideViewPort(true); // 将图⽚调整到适合 WebView 的⼤⼩ webSettings.setLoadWithOverviewMode(true); // 缩放⾄屏幕的⼤⼩// 缩放操作

webSettings.setSupportZoom(true); // ⽀持缩放,默认为 true

webSettings.setBuiltInZoomControls(true); // 设置内置的缩放控件,若为 false,则该 WebView 不可缩放webSettings.setDisplayZoomControls(false); // 隐藏原⽣的缩放控件

填坑记录

1、WebViewClient 类常⽤⽅法

mWebView.setWebViewClient(new MyWebViewClient());shouldOverrideUrlLoading()

在⽹页上的所有加载都经过这个⽅法,这个函数我们可以做很多操作。

onPageStarted()

开始载⼊页⾯调⽤的,我们可以设定⼀个 loading 的页⾯,告诉⽤户程序在等待⽹络响应。

onPageFinished()

在页⾯加载结束时调⽤。我们可以关闭 loading 条,切换程序动作。

onLoadResource()

在加载页⾯资源时会调⽤,每⼀个资源(⽐如图⽚)的加载都会调⽤⼀次。

onReceivedError()

加载页⾯出现错误时调⽤。2、WebChromeClient 类常⽤⽅法

mWebView.setWebChromeClient(new MyWebChromeClient());onProgressChanged()

获得⽹页的加载进度并显⽰。

onReceivedTitle()

获取 Web 页中的标题。

onJsAlert()

⽀持 javascript 的警告框。

onJsConfirm()

⽀持 javascript 的确认框。

onJsPrompt()

⽀持 javascript 输⼊框。3、 Https 和 Http 混合模式

从 Android 5.0 开始,WebView 默认不⽀持同时加载 Https 和 Http 资源。

解决⽅法:在webview加载页⾯之前,设置加载模式为 MIXED_CONTENT_ALWAYS_ALLOW

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}

4、安全问题

addJavascriptInterface

Android 4.2 以前,要采⽤拦截 prompt() 的⽅式进⾏漏洞修复;Android 4.2 以后,只需要对被调⽤的函数以@JavascriptInterface 进⾏注解。

searchBoxJavaBridge_、accessibility、accessibilityTraversal

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { mWebView.removeJavascriptInterface(\"searchBoxJavaBridge_\"); mWebView.removeJavascriptInterface(\"accessibility\");

mWebView.removeJavascriptInterface(\"accessibilityTraversal\");}

密码明⽂存储漏洞

webSettings.setSavePassword(false);

5、替换 WebView 的加载错误页⾯

@Override

public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); showCustErrorPage();}

private View mErrorView;

protected void showCustErrorPage() { // 移除WebView

ViewGroup webParentView = (ViewGroup) mWebViewInstance.getParent(); while (webParentView.getChildCount() > 0) { webParentView.removeViewAt(0); }

// ⽣成⾃定义错误页⾯ if (mErrorView == null) {

mErrorView = View.inflate(mContext, R.layout.webview_error, null); mErrorView.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { showWebViewPage();

mWebViewInstance.reload(); } }); }

// 替换为错误页⾯

ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(

ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT); webParentView.addView(mErrorView, 0, lp);}

protected void showWebViewPage() { // 移除⾃定义错误页⾯

ViewGroup webParentView = (ViewGroup) mErrorView.getParent(); while (webParentView.getChildCount() > 0) { webParentView.removeViewAt(0); }

// 替换为WebView

ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(

ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT); webParentView.addView(mWebViewInstance, 0, lp);}

6、WebView的内存泄露。

关于这个问题,我很难给你⼀个清晰的描述,你在⾕歌⾥搜 webview lead memory 能搜到很多结果 甚⾄还有给⾕歌提交的issue 哈哈,我也⽆法给出⼀个清晰的答案 在什么时候 什么版本那些⼿机上⼀定会出现内存泄露,

但是根据我⾃⼰的monkey结果来看,有时,webview内存泄露的情况还是很严重的,尤其是当你加载的页⾯⽐较庞⼤的时候。解决⽅案 我查了很多也⽤了很多,但是都不太理想,最后看了下微信和qq的做法,试了⼀下是⽬前效果最好的,就是 当你要⽤webview的时候,记得最好 另外单独开⼀个进程 去使⽤webview 并且当这个 进程结束时,请⼿动调⽤System.exit(0)。

这是⽬前对于webview 内存泄露 最好的解决⽅案。使⽤此⽅法 所有因为webview引发的 资源⽆法释放等问题 全部可以解决。

7、getSettings().setBuiltInZoomControls(true) 引发的crush。

这个⽅法调⽤以后 如果你触摸屏幕 弹出那个提⽰框还没消失的时候 你如果activity结束了 就会报错了。3.0以上 4.4以下很多⼿机会出现这种情况

所以为了规避他,我们通常是在activity的onDestroy⽅法⾥⼿动的将webiew设置成 setVisibility(View.GONE)8、onPageFinished 函数到底有⽤没有?

但其实根据我⾃⼰观察,这个函数并没有什么卵⽤,有的时候是提前结束,有的时候就迟迟⽆法结束,你信这个函数 还不如信上帝,甚⾄于onProgressChanged这个函数

都⽐onPageFinished 要准⼀些。如果你的产品经理坚持你⼀定要实现这种功能的话,我建议你 提早结束他,否则卡在那⽤户迟迟动不了 这种体验不好。

有空的同学可以跟⼀下源码,onPageFinished 在不同的内核⾥ 调⽤的时机都不⼀样。说实话 我也很醉。。。这个问题 有完美解决⽅案的 请知会我⼀下。。。9、后台⽆法释放js 导致耗电。

这个可能很少有⼈知道,我也是被投诉过 才了解,在有的⼿机⾥,你如果webview加载的html⾥ 有⼀些js ⼀直在执⾏⽐如动画之类的东西,如果此刻webview 挂在了后台

这些资源是不会被释放 ⽤户也⽆法感知。。。导致⼀直占有cpu 耗电特别快,所以⼤家记住了,如果遇到这种情况 请在onstop和onresume⾥分别把setJavaScriptEnabled();给设置成false和true。

10、如果实在不想⽤开额外进程的⽅式解决webview 内存泄露的问题,那么下⾯的⽅法很⼤程度上可以避免这种情况

public void releaseAllWebViewCallback() {

if (android.os.Build.VERSION.SDK_INT < 16) { try {

Field field = WebView.class.getDeclaredField(\"mWebViewCore\"); field = field.getType().getDeclaredField(\"mBrowserFrame\"); field = field.getType().getDeclaredField(\"sConfigCallback\"); field.setAccessible(true); field.set(null, null);

} catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); }

} catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } }

} else { try {

Field sConfigCallback = Class.forName(\"android.webkit.BrowserFrame\").getDeclaredField(\"sConfigCallback\"); if (sConfigCallback != null) {

sConfigCallback.setAccessible(true); sConfigCallback.set(null, null); }

} catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); }

} catch (ClassNotFoundException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); }

} catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } }

在webview的 destroy⽅法⾥ 调⽤这个⽅法就⾏了。

11、另外很多⼈ 不知道webview 实际上有⾃⼰⼀套完整的cookie机制的,利⽤好这个 可以⼤⼤增加对客户端的访问速度。实际上cookie就是存放在这个表⾥的。

很多⼈都想要⼀个效果:⽹页更新cookie 设置完cookie以后 不刷新页⾯即可⽣效。这个在2.3以下和2.3以上要实现的⽅法不太⼀样,所以要做⼀次兼容

public void updateCookies(String url, String value) {

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下 CookieSyncManager.createInstance(getContext().getApplicationContext()); }

CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.setCookie(url, value);

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { CookieSyncManager.getInstance().sync(); } }

总结

以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务