背景是这样的,我们的应用内嵌了webview,测试同学配测试连接的时候,在某部手机上,应用闪退了。
我就用了系统的webview,没做什么特殊处理,应该是网页的问题,但是具体是什么问题呢?
上午刚好有一点时间,所以我做了一下问题定位和排查,我是这样排查的:
step 1 继承 WebViewClient,查看有哪些HTTP请求,把一些可以的直接返回空
// setWebViewClient(new YeshenWebViewClient());
private final class YeshenWebViewClient extends WebViewClient {
...
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && request != null
&& request.getUrl() != null && request.getUrl().getHost() != null) {
String url = request.getUrl().toString();
WebResourceResponse response = fetch(url);
if (response != null) return response;
}
return super.shouldInterceptRequest(view, request);
}
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
WebResourceResponse response = fetch(url);
if (response != null) return response;
return super.shouldInterceptRequest(view, url);
}
private WebResourceResponse fetch(String url) {
if (url.equals("${可疑连接}")) {
return new WebResourceResponse("text/html", "utf-8",
new ByteArrayInputStream("".getBytes()));
}
Log.e("Yeshen", url);
return null;
}
}
在这个场景下,其实实际问题是,https://www.163.com 在魅族note2手机(Mozilla/5.0 (Linux; Android 5.1; M571C Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.127 Mobile Safari/537.36)上,在用原生webview加载是,会使应用闪退。
所以我把 https://www.163.com 的所以http请求都打印了出来,一个个试,看看那个HTTP请求比较可疑。
最后我还是试出来了,只要屏蔽了这个连接,就不会闪退:
https://static.ws.126.net/163/wap/f2e/milk_index/index.e7d25e8a.js
step 2 替换出错的js请求
- 把上述文件保存下来
- 做一下反序列化: https://beautifier.io/
- 保存在
/app/src/main/assets
目录下 - 在代码中这样读取
private WebResourceResponse fetch(String url) {
if (url.equals("https://static.ws.126.net/163/wap/f2e/milk_index/index.e7d25e8a.js")) {
return new WebResourceResponse("text/html", "utf-8",
new ByteArrayInputStream(readJsContent(getContext()).getBytes()));
}
Log.e("Yeshen", url);
return null;
}
final String readJsContent(Context context) {
StringBuilder js = new StringBuilder();
try {
InputStream is = context.getAssets().open("milk_index.js");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
js.append(line);
}
is.close();
} catch (Exception e) {/*ignore it*/
}
return js.toString();
}
step 3 阅读代码,打日志确定出问题的位置
可以这样打日志
console.log("tag #12");
我尝试了许久,在上面1.2万行代码中各种打日志。
打了许久的日志,我发现程序是有入口的,入口在 ./app/src/main.js
出错点也在这个里面,出错的主要是这三行代码
"serviceWorker" in navigator && navigator.serviceWorker.register("/service-worker-index.js").catch(function (e) {
return console.log(e)
}),
step 4 尝试复现问题
我用手机连接电脑,打开了调试模式,在chrome浏览器中,打开了 chrome://inspect
在其中输入了这样一行代码:
navigator.serviceWorker.register("")
应用如愿闪退。
玩~