最近做一款工具类app,要加入一个简单的搜索功能,为用户提供便利。
那有何难?直接用WebView加载一下百度和Google的搜索链接不就完了嘛...
经过分析,百度的搜索url是https://www.baidu.com/s?wd=keyword
,Google的搜索url是https://www.google.com/search?q=keyword
。身在天朝,先拿百度做个试验吧~
嗖嗖嗖代码出来了,最简单的WebView使用
private static final String BAIDU_SEARCH_URL = "https://www.baidu.com/s?wd=webtest";
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebView = new WebView(this);
setContentView(mWebView);
mWebView.loadUrl(BAIDU_SEARCH_URL);
}
结果上个图,恩,完美盗用了百度的成果
这时候,万恶的pm跳出来了,“咱们能把百度的脑袋砍了吗?”......OK,我懂你兄弟
虽然我也不知道这么做是否侵犯了百度的利益,但是既然pm提出来了,咱们也得给他实现不是。经过一番调查,最后确定了如下方案:
- 加载百度页面
- 加载完成的回调中,向页面注入JavaScript代码
- JavaScript代码将配置的dom元素移除
关键点就是怎么判断页面加载完成以及如何注入砍脑袋的JavaScript代码。
WebView有个回调类叫WebChromeClient,它里面有个onProgressChanged(WebView view, int newProgress)
的回调方法,每当dom树的加载进度变化时,就通知给我们的app。所以,我们可以近似地认为回调进度是100时就是页面加载完成的时刻。
那怎么确定需要删除的dom元素id呢?我们可以到Chrome的开发者工具找到百度脑袋的dom元素id,如下图所示
好了,万事俱备,上代码
// 需要隐藏的dom元素id
private static final String[] HIDE_DOM_IDS = {"page-hd", "page-tips"};
// 定义WebChromeClient
private WebChromeClient mSearchChromeClient = new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
Log.d(SEARCH_TAG, "on page progress changed and progress is " + newProgress);
// 进度是100就代表dom树加载完成了
if (newProgress == 100) {
mWebView.loadUrl(getDomOperationStatements(HIDE_DOM_IDS));
}
}
};
mWebView.setWebChromeClient(mSearchChromeClient);
public static String getDomOperationStatements(String[] hideDomIds) {
StringBuilder builder = new StringBuilder();
// add javascript prefix
builder.append("javascript:(function() { ");
for (String domId : hideDomIds) {
builder.append("var item = document.getElementById('").append(domId).append("');");
builder.append("item.parentNode.removeChild(item);");
}
// add javascript suffix
builder.append("})()");
return builder.toString();
}
可以看到百度脑袋一闪而过,被切掉了。闪这一下倒是比较容易解决,可以通过先mWebView.setVisibility(View.INVISIBLE)
,执行JavaScript代码1s后再mWebView.setVisibility(View.VISIBLE)
解决,就不再赘述了。
总结:虽然这个场景实用性不强,但可权且当做WebView操作页面元素的一个例子,提供一种自定义WebView的思路。