【Android面试题】高级UI面试题——Android WebView拦截请求的方式

194 阅读3分钟

Android WebView拦截请求的方式

这道题想考察什么?

考察WebView 的基本用法中拦截请求的方式,这个也是开发中常用的技能

考生应该如何回答?

如果想做webview的本地缓存或者拦截请求做其他的事情就设计到了拦截webview的请求。

如何去做呢?

我们先简单的回顾一下Webview loadUrl的方式。

WebView的基本用法相信大多数android开发者都是会使用的,最简单的就是调用个loadUrl方法,但是记得要在清单文件中添加网络权限。

mWebview = (WebView) findViewById(R.id.my_webview);
mWebview.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)         {
    	return false;
    }
});
mWebview.loadUrl("https://www.baidu.com/");

在Android自带的WebView中,如果需要对访问的URL或者资源进行拦截,主要涉及到WebViewClient中的三个方法:onPageStarted、shouldOverrideUrlLoading、shouldInterceptRequest。首先来分析onPageStarted方法和shouldOverrideUrlLoading方法,分别在两个方法以及onPageFinished方法中打印log。

a) 当用户使用WebView的loadUrl方法开启一个网页时,其中onPageStarted方法会执行,而shouldOverrideUrlLoading则不会执行 b) 当用户继续点击网页内的链接时,onPageStarted和shouldOverrideUrlLoading均会执行,并且shouldOverrideUrlLoading要先于onPageStarted方法执行 c) 当用户点击网页中的链接后,点击back,返回历史网页时,onPageStarted会执行,而shouldOverrideUrlLoading不会执行 综上所述,当需要对访问的网页进行策略控制时,需要在onPageStarted方法中进行拦截,如下示例代码:

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {  
    Log.d(TAG, "onPageStarted url is " + url);
    boolean res = checkUrl(url);
    //根据对URL的检查结果,进行不同的处理,
    //例如,当检查的URL不符合要求时,
    //可以加载本地安全页面,提示用户退出
    if (!res) {
        //停止加载原页面
        view.stopLoading();
        //加载安全页面
        view.loadUrl(LOCAL_SAFE_URL);
    }
}

然后,来分析一下shouldInterceptRequest(WebView view, String url),此方法从Android API 11(3.0)开始提供,位于WebViewClient 内,当用户使用WebView的loadUrl方法打开网页、点击网页中的链接、返回历史网页时,所有资源的加载均会调用shouldInterceptRequest方法

进行资源替换时,可以将网页资源,例如html、css、js、图片等存放在本地,在shouldInterceptRequest对WebView加载的资源进行拦截,当符合某种策略时,替换为本地的资源,资源的MIME类型可以采用以下方法获取: MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url)) 示例:

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    Log.d(TAG, "shouldInterceptRequest : " + url);
    Uri uri = Uri.parse(url);
    String localPath = "file://" + Environment.getExternalStorageDirectory().getAbsoluteFile() + "/www" + uri.getPath();
    File file = new File(localPath);
    try {
        URL localUri = new URL(localPath);
        if (localUri != null) {
            InputStream is = localUri.openConnection().getInputStream();
            WebResourceResponse resourceResponse = new WebResourceResponse(
 MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url)), "UTF-8", is);
            Log.d(TAG, "replace " + MimeTypeMap.getFileExtensionFromUrl(url));
            return resourceResponse;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return super.shouldInterceptRequest(view, url);
}

WebView中调用的每个请求都会经过那个拦截器,所以如果一个页面中又有超链接,那么依然会经过那个拦截器,所以上面Import new中有些图片没有加载出来。因为我是以本文形式获取响应的,并且是以utf-8作为编码的,所以有时会出现乱码。

详细关注公众号:Android老皮
还能解锁  《Android十大板块文档》 ,让学习更贴近未来实战。已形成PDF版

内容如下

1.Android车载应用开发系统学习指南(附项目实战)
2.Android Framework学习指南,助力成为系统级开发高手
3.2023最新Android中高级面试题汇总+解析,告别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到精通,构建高质量UI界面
6.Flutter技术解析与实战,跨平台首要之选
7.Kotlin从入门到实战,全方面提升架构基础
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 性能优化实战+360°全方面性能调优
10.Android零基础入门到精通,高手进阶之路