添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
飘逸的人字拖  ·  rdkit/ReleaseNotes.md ...·  6 月前    · 
小胡子的李子  ·  武汉市公安局·  7 月前    · 
乖乖的泡面  ·  故障排除 - Unity 手册·  1 年前    · 

在本文中,我们将了解如何使用 flutter_inappwebview 插件为我们的 WebView 实例创建自定义 Content Block。

内容拦截器通常用于拦截广告,但你也可以拦截任何其他内容。拦截行为包括隐藏元素、拦截负载,以及在 iOS 和 macOS 上从 WebView 请求中剥离 cookie。

请记住,一般来说,Content Blockers 不能实现与 AdBlock 或 AdBlock Plus 等专用 extension 相同级别的功能。Content Blockers 是一组规则,当 WebView 找到需要阻止的内容时,它将永远不会从 WebView 获得任何回调或通知。

通过 InAppWebViewSettings 类的 contentBlockers 属性,我们可以定义 WebView 将使用的 ContentBlockers 实例的列表。

ContentBlocker 内容过滤类

ContentBlock 类是我们定义内容拦截行为的类。每个属性包含一个操作属性和一个触发器属性。该操作告诉 WebView 在遇到与触发器匹配的对象时要做什么。触发器告诉 WebView 何时执行相应的操作。

下面是一个基本的例子:

initialSettings: InAppWebViewSettings(contentBlockers: [
  ContentBlocker(
    trigger: ContentBlockerTrigger(
      urlFilter: ".*",
      resourceType: [
        ContentBlockerTriggerResourceType.IMAGE,
        ContentBlockerTriggerResourceType.STYLE_SHEET
    action: ContentBlockerAction(
      type: ContentBlockerActionType.BLOCK

在这个例子中,我们说的是为每个 URL 阻止每个图像和样式表的加载。

将 triggers 触发器添加到 Content Blocker 内容阻止器

触发器必须定义所需的 urlFilter 属性,该属性将正则表达式指定为与 URL 匹配的字符串。其他属性是可选的,可以修改触发器的行为。例如,可以将触发器限制为特定域,或者在 WebView 找到与特定域匹配的触发器时不应用触发器。

下面是一个内容拦截器的例子,它带有一个针对图像和样式表资源的触发器,WebView 可以在任何域中找到这些资源,但是指定的域除外:

initialSettings: InAppWebViewSettings(contentBlockers: [
  ContentBlocker(
    trigger: ContentBlockerTrigger(
      urlFilter: ".*",
      resourceType: [
        ContentBlockerTriggerResourceType.IMAGE,
        ContentBlockerTriggerResourceType.STYLE_SHEET
      unlessDomain: ["example.com", "github.com", "pub.dev"]
    action: ContentBlockerAction(
      type: ContentBlockerActionType.BLOCK

对于更深层次的触发器自定义,您可以使用 ContentBlockerTrigger 的其他属性:

  • 如果 URL 匹配应该区分大小写。默认情况下,它是不区分大小写的。
  • Resource ceType: “ ContentBlockerTriggerResourceType”的列表,表示规则应该匹配的资源类型(浏览器打算如何使用资源)。如果未指定,则该规则匹配所有资源类型。
  • IfDomain: 与 URL 域匹配的字符串列表; 将操作限制为特定域的列表。值必须是小写的 ASCII,或非 ASCII 的小写字母代码。在前面添加 * 以匹配域和子域。它不能和“ unless Domain”一起使用。
  • Unless 域名: 与 URL 域名匹配的字符串列表; 在提供列表中的域名以外的任何站点上执行操作。值必须是小写的 ASCII,或非 ASCII 的小写字母代码。在前面添加 * 以匹配域和子域。它不能与“ ifDomain”一起使用。
  • LoadType: “ ContentBlockerTriggerLoadType”的列表,可以包括两个相互排斥的值之一。如果未指定,则该规则匹配所有加载类型。“ ContentBlockerTriggerLoadType.FIRST_PARTY”仅在资源与主页资源具有相同的方案、域和端口时触发。如果资源与主页资源来自不同的域,则“ ContentBlockerTriggerLoadType.THIRD_PARTY”触发器。
  • IfTopUrl: 与整个主文档 URL 匹配的字符串列表; 将操作限制为 URL 模式的特定列表。值必须是小写的 ASCII,或非 ASCII 的小写字母代码。它不能和“ unless TopUrl”一起使用。
  • Unless TopUrl: 与整个主文档 URL 匹配的字符串数组; 在所提供列表中的 URL 模式以外的任何站点上进行操作。值必须是小写的 ASCII,或非 ASCII 的小写字母代码。它不能与“ ifTopUrl”一起使用。
  • LoadContext: 指定加载上下文的字符串数组。
  • IfFrameUrl: 用于匹配 iframe URL 的正则表达式列表。
  • 检查每个特定属性的代码文档,以了解哪个平台支持该特性。

    向内容屏蔽器添加 actions 操作

    当触发器与资源匹配时,WebView 计算所有触发器并按顺序执行操作。

    将具有相似操作的规则组合在一起以提高性能。例如,首先指定阻止内容加载的规则,然后指定阻止 Cookie 的规则。

    操作只有两个有效属性: type 和 selector。操作类型是必需的。 如果类型是 ContentBlockerActionType.CSS_DISPLAY_NONE,也需要一个选择器; 否则,选择器是可选的。

    下面是一个简单的例子:

    initialSettings: InAppWebViewSettings(contentBlockers: [
      ContentBlocker(
        trigger: ContentBlockerTrigger(
          urlFilter: "https://flutter.dev/.*",
        action: ContentBlockerAction(
          type: ContentBlockerActionType.CSS_DISPLAY_NONE,
          selector: '.notification, .media, #developer-story'
    

    有效类型包括:

  • BLOCK: 停止加载资源。如果资源被缓存,缓存将被忽略。
  • BLOCK_COOKIES: 在将 Cookie 发送到服务器之前,从头中剥离 Cookie。这只能阻止 Cookie,否则 WebView 的隐私政策是可以接受的。结合“ IGNORE_PREVIOUS_RULES”不会覆盖浏览器的隐私设置。
  • CSS_DISPLAY_NONE: 基于 CSS 选择器隐藏页面元素。选择器字段包含选择器列表。任何匹配的元素都将其 display 属性设置为 none,这将隐藏它。
  • MAKE_HTTPS: 将 URL 从 http 更改为 https。具有指定(非默认)端口的 URL 和使用其他协议的链接不受影响。
  • IGNORE_PREVIOUS_RULES: 忽略以前触发的动作。
  • 检查每个特定类型的代码文档,以了解哪个平台支持它。

    创建一个简单的广告屏蔽器

    让我们用我们学到的知识创建一个简单的广告拦截器。

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      if (!kIsWeb &&
          kDebugMode &&
          defaultTargetPlatform == TargetPlatform.android) {
        await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
      runApp(const MaterialApp(home: MyApp()));
    class MyApp extends StatefulWidget {
      const MyApp({Key? key}) : super(key: key);
      @override
      State<MyApp> createState() => _MyAppState();
    class _MyAppState extends State<MyApp> {
      final GlobalKey webViewKey = GlobalKey();
      // list of Ad URL filters to be used to block ads loading.
      final adUrlFilters = [
        ".*.doubleclick.net/.*",
        ".*.ads.pubmatic.com/.*",
        ".*.googlesyndication.com/.*",
        ".*.google-analytics.com/.*",
        ".*.adservice.google.*/.*",
        ".*.adbrite.com/.*",
        ".*.exponential.com/.*",
        ".*.quantserve.com/.*",
        ".*.scorecardresearch.com/.*",
        ".*.zedo.com/.*",
        ".*.adsafeprotected.com/.*",
        ".*.teads.tv/.*",
        ".*.outbrain.com/.*"
      final List<ContentBlocker> contentBlockers = [];
      var contentBlockerEnabled = true;
      InAppWebViewController? webViewController;
      @override
      void initState() {
        super.initState();
        // for each Ad URL filter, add a Content Blocker to block its loading.
        for (final adUrlFilter in adUrlFilters) {
          contentBlockers.add(ContentBlocker(
              trigger: ContentBlockerTrigger(
                urlFilter: adUrlFilter,
              action: ContentBlockerAction(
                type: ContentBlockerActionType.BLOCK,
        // apply the "display: none" style to some HTML elements
        contentBlockers.add(ContentBlocker(
            trigger: ContentBlockerTrigger(
              urlFilter: ".*",
            action: ContentBlockerAction(
                type: ContentBlockerActionType.CSS_DISPLAY_NONE,
                selector: ".banner, .banners, .ads, .ad, .advert")));
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: const Text("Ads Content Blocker"),
              actions: [
                TextButton(
                  onPressed: () async {
                    contentBlockerEnabled = !contentBlockerEnabled;
                    if (contentBlockerEnabled) {
                      await webViewController?.setSettings(
                          settings: InAppWebViewSettings(
                              contentBlockers: contentBlockers));
                    } else {
                      await webViewController?.setSettings(
                          settings: InAppWebViewSettings(contentBlockers: []));
                    webViewController?.reload();
                    setState(() {});
                  style: TextButton.styleFrom(foregroundColor: Colors.white),
                  child: Text(contentBlockerEnabled ? 'Disable' : 'Enable'),
            body: SafeArea(
                child: Column(children: <Widget>[
              Expanded(
                child: Stack(
                  children: [
                    InAppWebView(
                      key: webViewKey,
                      initialUrlRequest:
                          URLRequest(url: WebUri('https://www.tomshardware.com/')),
                      initialSettings:
                          InAppWebViewSettings(contentBlockers: contentBlockers),
                      onWebViewCreated: (controller) {
                        webViewController = controller;
            ])));
    

    使用这些规则可以防止出现大量的广告,比如谷歌广告。

    单击禁用/启用按钮禁用或启用广告屏蔽功能。

    WebView 广告屏蔽器示例。

    github.com/ducafecat/f…

    如果本文对你有帮助,请转发让更多的朋友阅读。

    也许这个操作只要你 3 秒钟,对我来说是一个激励,感谢。

    祝你有一个美好的一天~

    微信 ducafecat

    wiki.ducafecat.tech

    video.ducafecat.tech

    分类:
    Android
    标签: