标签:
前言:生活的艰难,更会激发对梦想的渴望,但艰难的生活却往往会成为梦想的绊脚石
相关文章:
1、《WebView使用详解(一)——Native与JS相互调用(附JadX反编译)》
2、《WebView使用详解(二)——WebViewClient与常用事件监听》
上篇给大家简单讲了Webview中Native代码与JS相互调用的方法,这篇我们再讲讲有关各种拦截与处理的东东。
mWebView.setWebViewClient(new WebViewClient(){ @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); Log.d(TAG,"onPageStarted"); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); Log.d(TAG,"onPageFinished"); } });直接调用WebView.setWebViewClient方法即可设置WebViewClient回调,这里重写的两个函数,onPageStarted会在WebView开始加载网页时调用,onPageFinished会在加载结束时调用。这两个函数就可以完成我们开篇时的需求:在开始加载时显示进度条,在结束加载时隐藏进度条。
/** * 在开始加载网页时会回调 */ public void onPageStarted(WebView view, String url, Bitmap favicon) /** * 在结束加载网页时会回调 */ public void onPageFinished(WebView view, String url) /** * 拦截 url 跳转,在里边添加点击链接跳转或者操作 */ public boolean shouldOverrideUrlLoading(WebView view, String url) /** * 加载错误的时候会回调,在其中可做错误处理,比如再请求加载一次,或者提示404的错误页面 */ public void onReceivedError(WebView view, int errorCode,String description, String failingUrl) /** * 当接收到https错误时,会回调此函数,在其中可以做错误处理 */ public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error) /** * 在每一次请求资源时,都会通过这个函数来回调 */ public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return null; }上面的方法比较多,我们一个个来看
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.loadUrl("http://blog.csdn.net/harvic880925"); mWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { mWebView.loadUrl(url); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); mProgressDialog.show(); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); mProgressDialog.hide(); } }); } }效果图如下:
从效果图中可以明显看出,在加载页面的时候会显示圆形加载框,在加载成功以后会隐藏加载框。
public boolean shouldOverrideUrlLoading(WebView view, String url)这个函数会在加载超链接时回调过来;所以通过重写shouldOverrideUrlLoading,可以实现对网页中超链接的拦截;
public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; }
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new WebViewClient()); mWebView.loadUrl("http://blog.csdn.net/harvic880925"); } }效果图如下:
从效果图中可以看出即仅仅设置WebViewClient对象,使用它的默认回调就可以实现在WebView中加载在线URL了:
mWebView.setWebViewClient(new WebViewClient());
代码如下:
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.contains("blog.csdn.net")){ view.loadUrl("http://www.baidu.com"); }else { view.loadUrl(url); } return true; } }); mWebView.loadUrl("http://blog.csdn.net/harvic880925"); } }最关键的位置在:
public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.contains("blog.csdn.net")){ view.loadUrl("http://www.baidu.com"); }else { view.loadUrl(url); } return true; }如果在当前webview加载的url中包含“blog.csdn.net”,则将其转换成”www.baidu.com”
mWebView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.contains("blog.csdn.net")){ view.loadUrl("http://www.baidu.com"); } return false; } }所以相对而言,我们使用return false好像更方便,只需要对需要拦截的URL进行拦截,拦截以后,让WebView处理默认操作即可。
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)加载错误的时候会产生这个回调,在其中可做错误处理,比如我们可以加载一个错误提示页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 id="h">啊哈,出错了……</h1> </body> </html>然后在加载返回错误时,重新加载错误页面
mWebView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); mWebView.loadUrl("file:///android_asset/error.html"); } });效果图如下:
/** * 当接收到https错误时,会回调此函数,在其中可以做错误处理 */ public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { super.onReceivedSslError(view, handler, error); Log.e(TAG,"sslError:"+error.toString()); } mWebView.loadUrl("https://www.12306.cn/"); } }在这里仅仅重写onReceivedSslError,并调用super.onReceivedSslError(view, handler, error);来调用默认的处理方式,然后把错误日志打出来:
mWebView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { // 一定要注释掉! // super.onReceivedSslError(view, handler, error); handler.proceed(); Log.e(TAG,"sslError:"+error.toString()); } });这里做了两个改变:
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.cancel(); }所以默认是取消继续加载的,所以我们必须注释掉super.onReceivedSslError(view, handler, error)来取消这个默认行为!
mWebView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { // super.onReceivedSslError(view, handler, error); handler.proceed(); Log.e(TAG,"sslError:"+error.toString()); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); Log.e(TAG,"onReceivedError:"+errorCode+" "+description); } });
从日志中明显可以看出,只有onReceivedSslError的接收日志,所以在SSL出错时,是不会触发onReceivedError回调的
所以对于onReceivedSslError结论来了:
当出现SSL错误时,WebView默认是取消加载当前页面,只有去掉onReceivedSslError的默认操作,然后添加SslErrorHandler.proceed()才能继续加载出错页面
当HTTPS传输出现SSL错误时,错误会只通过onReceivedSslError回调传过来
public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return null; }该函数会在请求资源前调用,我们可以通过返回WebResourceResponse的处理结果来让WebView直接使用我们的处理结果。如果我们不想处理,则直接返回null,系统会继续加载该资源。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 id="h">欢迎光临启舰的blog</h1> <img src="http://localhost/qijian.png"/> </body> </html>然后是Native代码:
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new WebViewClient(){ @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { try { if (url.equals("http://localhost/qijian.png")) { AssetFileDescriptor fileDescriptor = getAssets().openFd("s07.jpg"); InputStream stream = fileDescriptor.createInputStream(); WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream); return response; } }catch (Exception e){ Log.e(TAG,e.getMessage()); } return super.shouldInterceptRequest(view, url); } }); mWebView.loadUrl("file:///android_asset/web.html"); }这里代码比较容易理解,当发现当前加载资源的url是我们自定义的http://localhost/qijian.png时,就直接将本地的图片s07.jpg作为结果返回。有关使用WebResourceResponse来构造结果的方法,我这里就不再展开了,内容实在是太多了,想具体了解针对不同情况如何返回结果的话,自己搜下相关资料吧。
/**
* 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次
*/
public void onLoadResource(WebView view, String url)
/**
* (WebView发生改变时调用)
* 可以参考http://www.it1352.com/191180.html的用法
*/
public void onScaleChanged(WebView view, float oldScale, float newScale)
/**
* 重写此方法才能够处理在浏览器中的按键事件。
* 是否让主程序同步处理Key Event事件,如过滤菜单快捷键的Key Event事件。
* 如果返回true,WebView不会处理Key Event,
* 如果返回false,Key Event总是由WebView处理。默认:false
*/
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
/**
* 是否重发POST请求数据,默认不重发。
*/
onFormResubmission(WebView view, Message dontResend, Message resend)
/**
* 更新访问历史
*/
doUpdateVisitedHistory(WebView view, String url, boolean isReload)
/**
* 通知主程序输入事件不是由WebView调用。是否让主程序处理WebView未处理的Input Event。
* 除了系统按键,WebView总是消耗掉输入事件或shouldOverrideKeyEvent返回true。
* 该方法由event 分发异步调用。注意:如果事件为MotionEvent,则事件的生命周期只存在方法调用过程中,
* 如果WebViewClient想要使用这个Event,则需要复制Event对象。
*/
onUnhandledInputEvent(WebView view, InputEvent event)
/**
* 通知主程序执行了自动登录请求。
*/
onReceivedLoginRequest(WebView view, String realm, String account, String args)
/**
* 通知主程序:WebView接收HTTP认证请求,主程序可以使用HttpAuthHandler为请求设置WebView响应。默认取消请求。
*/
onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
/**
* 通知主程序处理SSL客户端认证请求。如果需要提供密钥,主程序负责显示UI界面。
* 有三个响应方法:proceed(), cancel() 和 ignore()。
* 如果调用proceed()和cancel(),webview将会记住response,
* 对相同的host和port地址不再调用onReceivedClientCertRequest方法。
* 如果调用ignore()方法,webview则不会记住response。该方法在UI线程中执行,
* 在回调期间,连接被挂起。默认cancel(),即无客户端认证
*/
onReceivedClientCertRequest(WebView view, ClientCertRequest request)
public class MyActivity extends Activity { private WebView mWebView; private ProgressDialog mProgressDialog; private String TAG = "qijian"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = (WebView)findViewById(R.id.webview); mProgressDialog = new ProgressDialog(this); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new WebViewClient()); mWebView.loadUrl("http://blog.csdn.net/harvic880925/"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //改写物理返回键的逻辑 if(keyCode==KeyEvent.KEYCODE_BACK) { if(mWebView.canGoBack()) { mWebView.goBack();//返回上一页面 return true; } else { System.exit(0);//退出程序 } } return super.onKeyDown(keyCode, event); } }在未重写onKeyDown前的效果图:点击回退按钮,整个Activity就销毁了
重写onKeyDown后的效果图:
可见在重写onKeyDown后,点击回退按钮时,就会回退到WebView的上一个页面。
public class MyWebView extends WebView { private OnScrollChangedCallback mOnScrollChangedCallback; public MyWebView(Context context) { super(context); } public MyWebView(Context context, AttributeSet attrs) { super(context, attrs); } public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollChangedCallback != null) { mOnScrollChangedCallback.onScroll(l,t,oldl,oldt); } } public OnScrollChangedCallback getOnScrollChangedCallback() { return mOnScrollChangedCallback; } public void setOnScrollChangedCallback( final OnScrollChangedCallback onScrollChangedCallback) { mOnScrollChangedCallback = onScrollChangedCallback; } public static interface OnScrollChangedCallback { public void onScroll(int left,int top ,int oldLeft,int oldTop); } }这段代码难度不大,就不再细讲了。
Uri uri = Uri.parse("http://www.example.com"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent);这里是使用隐式Intent的方式来启用外部应用,有关隐式Intent的知识,可以参考:
如果本文有帮到你,记得加关注哦
源码下载地址:http://download.csdn.net/detail/harvic880925/9534186
请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/51523983 谢谢
如果你喜欢我的文章,那么你将会更喜欢我的微信公众号,将定期推送博主最新文章与收集干货分享给大家(一周一次)
WebView使用详解(二)——WebViewClient与常用事件监听
标签:
原文地址:http://blog.csdn.net/harvic880925/article/details/51523983