code小生,一个专注 Android 领域的技术平台

公众号回复 Android 加入我的安卓技术群

作者:Dotry链接:https://www.jianshu.com/p/cd1aeed9e3bd声明:本文已获Dotry授权发表,转发等请联系原作者授权

前言

说起网页广告,那真是让人又恨又爱,它们不但占用了网页的可视控件,分散用户的注意力,还有些浮动广告干扰甚至误导用户操作。但是广告又是开发者重要的收入来源之一,比如我们在做浏览器的同时需要接入新的广告,同时又要过滤掉网页中的广告,这就是一个很正常的现象。说起应用广告过滤对于PC端来说可能更方便,网上有大量各种广告过滤插件。但对于Android等移动端来说就不那么友好了。Android应用的广告过滤方案大概可以分为以下几种方式

Android广告过滤.png

分析

从上图来看,虽然有这几种方式,甚至还有一些方式没有列出来,但其根本可以用一句话来概括:根据规则来过滤URL。其原理可以简单概括如下:

过滤广告很简单,就是判断页面是否有广告,如果有广告,则不加载这条广告。具体就要从网页加载原理说起了。我们知道网页其实就是html+css+js,请求网页的时候,会先根据url来下载html文件,并进行解析,解析到需要加载的css和js以及图片视频等资源的时候,就会去下载这些文件。也就是说,每一个文件的下载都对应一条url,打开一个网页,可能需要下载数十上百个文件,也就有这么多的url。所以我们可以针对每一条url进行判断,看其到底是不是会产生广告的url,或者就是广告的资源。

1. 代理方式:

1.1 服务器方式:对于一个应用如果数据来源于指定的服务器,只需要我们在指定的服务器里控制好资源请求与分发即可,那么对于移动应用来说去广告的效率更好,因为资源的过滤运算均在服务器,而不在移动端,相对来说更可维护,但这样的对服务器的任务又是一个问题了。

1.2  AdBlockplus:  世界上的网站何止千万,而这些网站的内容又随时都有可能发生变化。因此,AdBlockPlus想出了一个解决方案:

通过社区来维护一个规则表,然后根据这个规则表来过滤url,同时让用户自己动手,参与到制作这个规则表的过程中来,以成千上万的用户来对抗千变万化的广告。

但是一个app是怎么能够对整个手机的流量进行过滤的呢?

其实很简单,AdBlockPlus自动对手机设置了代理,代理到本机的2020端口,然后建立了一个简单的代理服务器,将所有的网络请求都统一通过这个代理来处理,从而达到全局的广告过滤效果。当然,当使用数据流量的时候,需要root权限,在4.0版本以上的wifi下的代理设置,也需要root权限,或者手动进行设置。我们先不管AdBlockPlus的代理服务器那部分功能,只看其核心的部分,也就是下载并读取规则文件,然后根据规则文件来判断url是否应该被过滤。如果你看过其安卓源码,你就会惊讶的发现,里面居然是用jni实现的,再仔细看的话,会发现jni的代码只是封装了静态链接库里面的内容,真正干活的部分都在静态链接库里,至于静态链接库里面的源码,就得装上git,hg,然后按照使用说明,才能同步下来整个代码库。这还不算完,因为估计是为了能跨平台使用,其核心部分代码是用js写的。AdBlockPlus就是通过V8引擎来执行js代码的,而js代码和V8引擎,都先通过交叉编译,被整合到了静态链接库中,最后通过jni封装以后,编译成动态链接库来Android使用。

可以说AdBlockPlus的核心就是对规则库的解析和匹配了,所以如果想修改AdBlockPlus的核心代码,则需要修改js、编译V8才行,或者使用java完全重写js代码的内容,而如果只想快速的将AdBlockPlus的广告过滤功能应用到自己的app中,就只能把原封不动的使用现成的模块了。

2. WebView自处理:

2.1  shouldInterceptRequest拦截:通过WebViewClient的源代码发现里面有个回调方法WebResourceResponse shouldInterceptRequest(WebView view, String url)这个方法中的url参数可以获取到所有的请求链接,我们需要一个规则文件里面包含大量广告host,每次获取url判断host规则文件中是否包含次链接/js名称/规则,对url进行解析对比判断是否为广告,如果是就对其进行拦截。

2.2 onPageFinished过滤:既然PC端能够通过js实现广告过滤,那么Android端同样也可以实现,即通过webview调用js脚本即可。

  /*** 注入js代码,获取当前页面所有的img** @param view WebView*/private void parseHTML(WebView view) {view.loadUrl("javascript:function getImgslist() {\n" +"  var imgs = document.querySelectorAll(\"body img\");\n" +"\n" +"  if (imgs && imgs.length <= 0) return \"\";\n" +"  var imgsArr = [].slice\n" +"    .call(imgs)\n" +"    .map(function(el) {\n" +"      return el.src;\n" +"    })\n" +"    .filter(Boolean);\n" +"\n" +"  return imgsArr;\n" +"}\n" +"window.local_obj.showSource(getImgslist());");}

可在方法onPageFinished 方法中调用该脚本,即可以实现相关功能。

总结

以上为广告过滤在Android中使用的几种方案,简单的概括为:在应用发起请求或者收请求去按照规则过滤相关url。当然广告过滤的方法远不止这几种,如果有其他方式欢迎交流讨论,但规则始终逃不过按照规则过滤url。

以下为AdBlockplus 维护的几个过滤表(过滤强度依次减弱):https://easylist-downloads.adblockplus.org/easylistchina+easylist.txthttps://easylist-downloads.adblockplus.org/easylistchina.txthttps://adfiltering-rules.googlecode.com/svn/trunk/lastest/rules_for_ABP.txt

推荐阅读仿知乎内容广告栏 WindowImageView监听WebView页面上所有的图片

扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~

Android 应用广告过滤几种方式相关推荐

  1. Android应用广告过滤几种方式

    前言 说起网页广告,那真是让人又恨又爱,它们不但占用了网页的可视控件,分散用户的注意力,还有些浮动广告干扰甚至误导用户操作.但是广告又是开发者重要的收入来源之一,同样作为一名开发者,还是挺能理解的.比 ...

  2. android ui 最新教程,Android更新UI的五种方式,androidui五种

    Android更新UI的五种方式,androidui五种handler.post activity.runOnUiThread view.post handler+Thread AsyncTask 例 ...

  3. android注册广播两种方式,Android 注册广播的两种方式对比

    Android 注册广播的两种方式对比 1.常驻型广播 常驻型广播,当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接受到, 他的注册方式就是在你的应用程序中的AndroidManif ...

  4. android 图片方法,分享实现Android图片选择的两种方式

    Android选择图片的两种方式: 第一种:单张选取 通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTU ...

  5. android使用其他应用打开方式,Android 启动activity的4种方式及打开其他应用的activity的坑...

    Android启动的四种方式分别为standard,singleTop,singleTask,singleInstence. standard是最常见的activity启动方式,也是默认的启动的方式. ...

  6. android视频播放的方法,Android实现视频播放的几种方式

    Android实现视频播放的3种方式 Android提供了常见的视频编码,解码机制,使用Android自带的MediaPlayer,MediaController等类可以很方便的实现视频播放的功能.支 ...

  7. android开启gps功能,android 打开GPS的几种方式

    1.在讨论打开gps的之前先看下如何检测gps的开关情况: 方式一: boolean gpsEnabled = locationManager.isProviderEnabled(LocationMa ...

  8. [Android开发]Android更新UI的五种方式

    Android更新UI的五种方式: 1.handler.post 2.activity.runOnUiThread 3.view.post 4.handler+Thread 5.AsyncTask 下 ...

  9. 【Android】Android 彩信发送的两种方式+源代码

    Android  彩信发送的两种方式 第一种:直接调用彩信发送接口 实现代码如下, Intent intent = new Intent(Intent.ACTION_SEND); intent.add ...

最新文章

  1. 骚操作 !IDEA 防止写代码沉迷插件 !
  2. 高颜值俄罗斯天才少女加入华为,曾获“编程界的奥林匹克”世界冠军
  3. ubuntu12.04中shell脚本无法使用source的原因及解决方法
  4. (四)JS基础知识一(深入分析变量类型和计算)【不会变量,别说你会JS】
  5. SAP ui5 setModel 的核心逻辑
  6. 封头名义厚度如何圆整_松原封头价格
  7. OpenSSL的托管项目
  8. X++中对字符串进行操作的函数
  9. update mysql.user set password_使用update命令来修改Mysql的root密码
  10. TOMCAT 优化设置
  11. win系统服务器怎么清理内存,windows服务器内存清理
  12. 3dmax疯狂模渲大师软件有什么使用指南?疯狂模渲大师的目录,教你怎么使用疯狂模渲大师,疯狂模渲大师其实并不难!
  13. 数据库实验第七周【集合查询数据更新】
  14. js获取手机型号和系统
  15. ccxprocess启动项可以禁用么_启动项禁用
  16. JWS-Exception
  17. Android自定义控件之拓展TextView(ExpandTextView)
  18. JAVA社交平台项目第七天 JUC多线程
  19. mysql 社区版 tokudb,TokuDB·社区八卦·TokuDB团队
  20. 已开源!Flutter 基于分帧渲染的流畅度优化组件 Keframe

热门文章

  1. 【Proteus仿真】Arduino UNO利用Stepper库实现uln2003驱动步进电机转动
  2. 手机计算机隐藏,手机计算机自带的隐藏功能,我也是现在才知道,功能比你想得多...
  3. 高等代数 多项式环(第7章)3 一元多项式的根与不可约多项式
  4. 对待二手车过户要理性
  5. A survey on challenges and progresses in blockchain technologies区块链综述
  6. python提取cad坐标_教你一个CAD坐标提取的小技巧
  7. AndroidStudio中Files under the “build“ folder are generated and should not be edited的解决方法
  8. 台式计算机经常使用的硬盘是什么尺寸,台式机硬盘和笔记本硬盘能通用吗?有什么区别?...
  9. 基于飞凌i.MX6Q-C核心板搭建3D相机
  10. 《穷查理宝典》听书笔记