Android WebView修改加载页面的DOM结构

最近做一款工具类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);

结果上个图,恩,完美盗用了百度的成果

关键点就是怎么判断页面加载完成以及如何注入砍脑袋的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();