近日,在把某网站用WebView打包到App里面的时候,出现的一个麻烦。看下图
额,有广告。不影响阅读体验的广告都是可以接受的。但是有一问题是因为有一个广告div比屏幕要大,导致该网页在在移动端上可以左右滑动,这个就没法忍受了,看下图
没办法了,只能把广告去掉了.
首先看看集成网页的代码.
private WebView webView;
private WebSettings settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
webView = (WebView) findViewById(web);
//设置WebView属性,能够执行Javascript脚本
settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAppCacheEnabled(true);
webView.setWebViewClient(new NoAdWebViewClient());
//加载需要显示的网页
webView.loadUrl("http://champion.gg/");
}
为了支持离线浏览,打开了WebView的默认缓存,设置支持js支持,设置WebClient,这里的NoAdWebViewClient在下面可以看到,在WebViewClient里面去掉广告.
@Override
//设置回退
//覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack(); //goBack()表示返回WebView的上一页面
return true;
}
return false;
}
重写Activity的onKeyDown简单back案件,当网页可以back的时候让网页回到上一页面.
来看一下NoAdWebViewClient的关键代码:
继承系统的WebViewClient,然后重写onPageFinished方法。
package com.jelly.championgg;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* Created by BrainWang on 05/01/2016.
*/
public class NoAdWebViewClient extends WebViewClient {
private Context context;
public NoAdWebViewClient(Context context) {
this.context = context;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String js = ADFilterTool.getClearAdDivJs(context);
Log.v("adJs",js);
view.loadUrl(js);
}
}
在onPageFinished里面外面执行的了一段Js,来看一看这段js(以下js为了方便阅读,经过整理):
javascript:
var adDiv0= document.getElementById('div-gpt-ad-1443488528500-4');
if(adDiv0 != null)
adDiv0.parentNode.removeChild(adDiv0);
var adDiv1= document.getElementById('div-gpt-ad-1443727656867-1');
if(adDiv1 != null)
adDiv1.parentNode.removeChild(adDiv1);
var adDiv2= document.getElementById('div-gpt-ad-1443488528500-5');
if(adDiv2 != null)
adDiv2.parentNode.removeChild(adDiv2);
...
去掉广告的原理很简单,注入一段js把显示广告的div删除就ok了,来看一下生成js的代码:
public static String getClearAdDivJs(Context context){
String js = "javascript:";
Resources res = context.getResources();
String[] adDivs = res.getStringArray(R.array.adBlockDiv);
for(int i=0;i<adDivs.length;i++){
js += "var adDiv"+i+"= document.getElementById('"+adDivs[i]+"');if(adDiv"+i+" != null)adDiv"+i+".parentNode.removeChild(adDiv"+i+");";
}
return js;
}
通过arrays.xml去管理去要去掉的广告div,遍历广告divId的集合,组合成一段js代码,注入到网页中去掉广告.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="adBlockDiv">
<item>div-gpt-ad-1443488528500-4</item>
<item>div-gpt-ad-1443727656867-1</item>
<item>div-gpt-ad-1443488528500-5</item>
<item>div-gpt-ad-1443488528500-6</item>
<item>div-gpt-ad-1443488528500-7</item>
<item>div-gpt-ad-1443727656867-0</item>
<item>div-gpt-ad-1443488528500-2</item>
<item>div-gpt-ad-1443488528500-3</item>
<item>div-gpt-ad-1443488528500-1</item>
</string-array>
</resources>
那么这些广告div的Id是如何获取的呢?我们通过Chrome浏览器可以很方便的获取到这些Id,可以看到通过F12的调试模式可以轻易的获取到广告div的Id
完成后我们就可以看到没有广告的页面了,完成效果。
其实这里还有一个问题,当网络比较慢的情况下,我们的网页会一直加载,然后当还没有调用onPageFinished的时候,用户就已经开始操作了,所以我们可以优化一下这种方式:
package com.jelly.championgg;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* Created by BrainWang on 05/01/2016.
*/
public class NoAdWebViewClient extends WebViewClient {
private Context context;
private WebView webView;
private boolean isClose;
public NoAdWebViewClient(Context context,WebView webView) {
this.context = context;
this.webView = webView;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if(isClose){ //如果线程正在运行就不用重新开启一个线程了
return;
}
new Thread(new Runnable() {
@Override
public void run() {
isClose = true;
while (isClose){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0x001);
}
}
}).start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
String js = ADFilterTool.getClearAdDivJs(context);
Log.v("adJs",js);
webView.loadUrl(js);
}
};
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
isClose = false;
}
}
在NoAdWebViewClient里面我们重写onPageStarted方法,并且开启一个线程,每1秒的循环注入js,在这里由于不能在子线程里面操作WebView,所以利用Handler去注入js.并且在onPageFinished内关闭线程.这样之后,即使网络很慢,在没有回调onPageFinished的时候,也不会出现广告了。