Skip to content

Releases

v13.2 · 常驻通知也可消除

Choose a tag to compare

@zmn001125 zmn001125 released this 19 Oct 14:28

常驻通知(音乐 / 下载 / 导航 / 前台服务)现在也能被规则消除了

先说为什么之前「消不掉」

不是我们漏做了——代码里没有任何跳过常驻通知的逻辑,cancelNotification 是照常调的。
真正的原因是 Android 平台行为:常驻通知由应用的前台服务持有,取消掉之后几十毫秒内,
应用就会用完全相同的内容重发同一条通知。所以我们此前只能「来一条删一条」。

这次改用系统的「打盹」机制

对标了那个能做到「一次操作、长期有效、恢复要把时间调到一年后」的 App 后改道:

listener.snoozeNotification(key, 1年)

snooze 是系统侧的持久状态(存在 system_server 的 NotificationManagerService 里),
休眠期内同一条通知(同 key)再更新也不会显示——一次操作,长期有效。
项目的「推迟」动作底层本来就在调用同一个 API,所以零新增 API 依赖。

怎么用

规则编辑页 → 勾选「消除」→ 下面出现两个子开关:

开关 作用
静音 先把该通知所属渠道静音,再消除(渠道级,影响该渠道后续通知,原始设置已留底可恢复)
常驻通知 命中带「进行中」标记的通知时,用系统打盹让它休眠约 1 年

「常驻通知」的语义(注意事项已在开关下方显示)

  • 命中音乐 / 下载 / 导航 / 前台服务等常驻通知时,休眠约 1 年
  • 休眠期内同一条通知再更新(比如播放进度)也不会回来,且不需要每次重发都删一次
  • 只影响这一条通知,不影响该应用的其他常驻通知
  • 到期后自动恢复,届时规则会重新判定(所以想提前恢复,把系统时间往后调即可)
  • 若应用改用别的通知或方式展示,可能仍压不住;系统自身的常驻通知(系统更新、安全提示等)不建议消除

实现上守住的两条

  • 不会「永远不恢复」:snooze 期间源 App 每秒更新进度,若那时再打盹一次会把到期时间
    不断刷新。所以加了一张抑制表,抑制期内直接跳过、不重复打盹;到期自动移除并恢复判定。
  • 不违反 V11.5 红线:不是「丢弃式节流」——内容一次不丢,只是被抑制的那条不再反复出现。

其它

  • 新增 BlockOngoingTest 8 例(含「旧规则 JSON 无 blockOngoing 键 → false」的零迁移断言)
  • 489 单测全绿;versionCode 24 / versionName 13.2
  • 真机验收重点:① 常驻通知是否真的消失且不再回来;② 同 App 的其他常驻通知是否不受影响;
    ③ 取消勾选后 / 关闭总开关后,之前被压住的常驻通知是否能恢复显示

apk sha256: 5507415b3540275e5a2c72cee8dd81568416339b3c1c2cc467de3b679025838d
签名证书 SHA-256: ecff994dd1a1bc6e4609088d1ca0f8b8394a63bf6a27c5b70b2fe8d58587d572

v13.1 · 耗电优化

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 17:18

耗电优化(保留全部功能)

针对「耗电 18%」做了全仓性能审计,定位到 8 处放大器,全部只降开销不改语义:

🔴 最大的一处

  • 媒体兜底轮询原本无条件常开:attach() 里就启动了 15 秒一次的循环,
    即使没有任何规则引用 media.* 也照跑 —— 一天 5760 次空转唤醒,
    而前台服务不让进程进入 Doze,这些唤醒全部按满速执行。
    现在由 setPollingEnabled() 随开关启停,没用到就循环根本不存在;
    同时把播放中 500ms → 1s、空闲 15s → 60s(歌词换句粒度 2~5 秒,1 秒足够跟手)。

🔴 放歌时的放大器

  • 媒体内容一变就重扫整个通知栏:一次 = 1 次 binder + 每条通知的全量 extras dump
    • 黑名单查询 + 可能的数据库写。几十条 × 每 2~5 秒 = 每分钟上千次写。
      现在改为 1.5 秒合并执行(跑的永远是最新一次,不是丢弃——
      V11.5 的教训是丢弃会永久丢内容),并对「没有流水行、且没有 media 规则作用域可能匹配」
      的通知直接跳过 extras dump。

🟠 每条通知都在做的重复工作

  • 结论同值也写库:进度/音乐通知每秒刷新,命中的规则却不变 → 每秒写一组完全相同的值。
    现在统一走 writeResult(),签名相同一次 UPDATE 都不发。
  • stats_daily 每条通知 3 条写语句:新行不再重复 UPDATE appName,
    且 refreshAppName 加了 AND appName <> ?(名字没变就不重写那一行)。
  • 黑名单每条通知一次 SELECT EXISTS → 进程内 Set 缓存(写操作失效)。
  • 总开关每条通知一次 DataStore 收集 → SettingsStore 进程内快照
    (唯一写入点是 setMasterEnabled,备份恢复也走它,不会陈旧)。
  • extras 指纹对每个值跑一次正则 → 改成常量时间判定(媒体类通知 30~50 个键)。

🟡 其它

  • 弹幕同屏上限 24 → 12(每条都是滚动期间每帧重绘的半透明全屏宽图层;
    12 仍远超「超过 5 条」的原始要求)。若你需要 24,告诉我改回来。
  • 命中日志 i → d(release 下不再写 logd)。

想进一步优化?告诉我这三项,我可以按你的用法再收窄

  1. 有没有规则勾选了 media.* 字段(决定媒体采集是否开启);
  2. 常驻通知(前台服务)开关是开着还是关着;
  3. 主要用弹幕 / 悬浮,还是只用消除和替换。

其它

  • 481 条单测全绿
  • versionCode 23 / versionName 13.1
  • 文档新增「耗电红线」(需求文档 §5 第 10 条)与使用说明常见问答

apk sha256: 86a5a281ea6f99987da409030319f7c8203e08d1d74bfbcb06ed295af100a2a6
签名证书 SHA-256: ecff994dd1a1bc6e4609088d1ca0f8b8394a63bf6a27c5b70b2fe8d58587d572

v13.0 · 规则分组

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 17:04

规则分组(归类标签)

一条规则可以打上任意多个分组标签,规则列表顶部出现「全部 + 各分组」的 tab,点一下只看该分组。

  • 编辑页新增「分组(归类标签)」区块:新建分组、点已有分组一键加入、已选标签点一下移除
  • 卡片上列出该规则所属的全部分组
  • 分组只是归类,完全不影响匹配判定——同一条规则在多个分组 tab 下行为一致
  • 排序仍是全局优先级:只有「全部」tab 下可拖动调顺序(分组视图会提示切回「全部」)
  • 零迁移:旧规则 JSON 无 groups 键 → 空列表,覆盖安装数据不丢

其它

  • 481 条单测全绿(新增 10 条 RuleGroups 纯函数单测)
  • versionCode 22 / versionName 13.0

apk sha256: a5e6c48509a9236425172c0ed1ca0791473ea553f4b678da2ead98cbba0e3461
签名证书 SHA-256: ecff994dd1a1bc6e4609088d1ca0f8b8394a63bf6a27c5b70b2fe8d58587d572

v12.2 — 分组匹配模式

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 16:05

新增:分组匹配模式(TEXT_GROUPS)

关键词分多组:组间 AND(每组都要满足),组内可选「任一出现 / 全部出现」。

典型用法——「必须出现 true,且 salt、nest 任一出现」:

  • 第 1 组填 true
  • 第 2 组填 salt、nest,选「任一出现」

每个关键词在任一被选字段中查找,可以分别出现在不同字段(如 true 在标题、salt 在正文)。组可随意增删。

为什么加这个模式

既有七模式都表达不了「组间 AND + 组内 OR」:

  • 包含全部 → salt 和 nest 必须都出现
  • 包含任一 → 太松
  • 包含 A 且不含 B → 第二组是否定
  • 正则 → 逐字段匹配,不能跨字段组合

其他

  • 规则编辑页「分组匹配」分支:每组一张卡片(组内模式二选一 + 删除组 + 关键词编辑)
  • App 内「使用说明」同步该模式说明
  • 旧规则 JSON 无该字段 → 自动零迁移,行为不变
  • 471 项单元测试全绿

签名:CN=nf(证书 SHA-256 ecff994d…87d572,与历版同密钥库,可直接覆盖升级)
文件 SHA-256:9d14b7670ef38521207966a7d05bd49881736f6b52a9d3b3693d3aaef3b31849

v12.1 — 媒体字段实时驱动规则 + 条件目标规则多选 + 已选App可删

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 14:58

v12.1 — 媒体字段实时驱动规则 + 条件目标规则多选 + 已选 App 可删

三个来自真机使用的修复:

① media.playing 变化后规则立即生效(修「只有第一次生效」)

以前媒体字段变化时只会重跑「播放器自己包名、且已进过流水」的通知,导致:

  • 引用 media.playing 的规则只在首次命中时生效一次;
  • 用「检测 media.playing 为 false」做悬浮显示条件(命中时清除某规则的悬浮窗)完全不触发。

现在媒体字段变化时对通知栏全部存活通知重跑引用 media.* 的规则——匹配、动作、
命中事件全链路走通。典型场景:「暂停播放 → 撤掉某条规则的悬浮窗」即刻生效,
不需要播放器重发通知。已有流水的通知同时就地刷新内容;没有流水的存量通知只求值、不写记录。

② 悬浮显示条件的目标规则支持多选

「满足时作用于」从单选改为多选:勾选『当前规则』= 只作用于本条规则自己的悬浮窗;
多选其他规则 = 一次控制多扇窗(各用它们自己的样式与内容)。V12.0 配过的单选目标
会自动兼容保留。

③ 已选 App 可以删除了

规则作用范围(仅指定 App / 全局排除)与悬浮显示条件里的已选 App 标签,
现在点一下标签即可移除(标签带关闭图标),「选择 App」按钮仍用于增选。

升级说明

  • 签名证书与历代一致(SHA-256 见下),可直接覆盖升级,规则 / 流水 / 设置不丢。
  • minSdk 26(Android 8.0+);versionCode 20 / versionName 12.1。

校验信息

  • 签名证书 SHA-256:ecff994dd1a1bc6e4609088d1ca0f8b8394a63bf6a27c5b70b2fe8d58587d572
  • 文件 SHA-256:2b1a9b84b60ed1b2e6d5bda53f1a93d2ae66f57a501078077cd7cc47a15d3125

源码:https://github.com/zmn001125/notification-filter (GPL-3.0)

v12.0 — 悬浮窗一规则一窗并存 + 显示条件可指定目标规则

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 14:21

v12.0 — 悬浮窗一规则一窗并存 + 显示条件可指定目标规则

新功能

① 不同规则的悬浮窗可以同时存在,互不顶掉

  • 以前所有规则共用同一个悬浮窗,后命中的规则会把前一个顶掉。
  • 现在每条规则拥有自己的悬浮窗(按规则 id 区分),可以同时显示多个,各自独立。
  • 同一个规则连续命中时仍然是「原地换内容」(不闪烁、不跳位置,沿用 V9.3 行为)。
  • 两条规则恰好配了同一个停靠位置时,窗口会按 14dp 逐级错开,不会完全重叠。
  • 同时最多 8 个悬浮窗(安全上限,超出撤最早的);点「清除屏幕显示」全部撤掉。

② 悬浮显示条件可以指定「作用到哪条规则」

  • 每条显示条件新增「满足时作用于」选项:
    • 留空 = 当前规则(默认,与以前完全一致);
    • 选某条规则 = 条件成立时显示/清除那条规则自己的悬浮窗(用那条规则自己的样式与内容)。
  • 例如:规则 A(任意通知命中)的条件指向规则 B(天气规则),则任意通知出现时弹出天气悬浮窗。
  • 「立即清除悬浮」现在也只撤对应的那一个窗,不再波及别人的窗口。

③ 媒体字段采集性能优化

  • 媒体会话字段的读取从主线程下沉到协程线程批量回写,播放中每秒读取不再占主线程。

安装

  1. 下载 notification-filter-v12.0-release.apk(约 12.7 MB)。
  2. 卸载旧版或直接覆盖安装(签名证书未变,SHA-256 见下方,覆盖升级不会丢数据)。
  3. minSdk 26(Android 8.0+);versionCode 19 / versionName 12.0。

校验信息

  • 签名证书 SHA-256:ecff994dd1a1bc6e4609088d1ca0f8b8394a63bf6a27c5b70b2fe8d58587d572(与历代版本一致)
  • 文件 SHA-256:fb4265feabaad45fc636a5d947b9c589ad00f8e7d1f56edcfad65fad47773f6a

说明

v11.5 — 内容变化时规则/动作真正重跑(移除 1.2s 节流)

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 11:56

上一版只修好了「流水显示」,规则本身仍被 1.2 秒节流挡住,所以你会看到「只拿到第一次出现的内容」。这一版把节流整层去掉了。

改了什么

删掉「同一通知 1.2 秒内只处理一次」的时间窗节流。它在窗口内会整条丢弃更新,后果有两个:

  1. 只更新一次的通知(如「待取件」→「已签收」)内容永久丢失;
  2. 规则完全不跟着跑 —— 规则匹配、内容提取/聚合({reN} / {itemsN})、动作(弹幕/悬浮/替换/朗读)都拿不到新内容。

现在:只要内容变了,就完整跑一遍

内容指纹判定(任意字段变化)→ 规则匹配 → 内容提取 / 聚合录制 → 动作执行 → 流水就地刷新

弹幕 / 悬浮 / 替换 / 朗读都会用变化后的新内容重新执行。

刷屏怎么保证

不靠节流,靠两道已有机制:

  • 指纹去重:内容完全相同的重复投递照样整条跳过(不会白跑);
  • 合并成一行:一条存活通知在流水里始终只占一行,内容原地刷新,不新增行、不跳位置。

⚠️ 唯一需要你留意的:如果给每秒都在变的通知(音乐进度、下载进度)配了弹幕/朗读规则,
现在会按变化频率真实执行(这正是"每次变化都要拿到"的语义)。嫌吵的话,规则里加个「设备状态 /
作用范围」收窄,或者告诉我,我给动作单独加一个「渲染结果相同时不重复执行」的去重。

安装

notification-filter-v11.5-release.apk · versionCode 15 · Android 8.0+ · 覆盖安装即可(同签名)

  • 签名证书 SHA-256:ECFF994DD1A1BC6E4609088D1CA0F8B8394A63BF6A27C5B70B2FE8D58587D572
  • 文件 SHA-256:fdf21ae2c964641fa468f3ea6da546124c37ee344a270b3281569a48fab8e2c0

验证

450 例单测全绿。本次是「去掉一层逻辑」,改动集中在 NotificationPipeline:
删除 recentHandledAt、MIN_HANDLE_INTERVAL_MS 与节流分支(净 -64 行),
保留指纹去重与 upsertRecord 合并。

许可:GPL-3.0(二改后分发须同样开源)。

v11.4 — 修复通知内容实时更新 + Android 正则断言兼容

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 11:48

修两个真问题:通知内容更新拿不到、正则断言在手机上不生效。

1)通知还在、字段也在变,但列表一直显示旧内容

根因有两层,都修了:

  • 内容指纹(判断"这条通知是不是新内容")此前只签了 android.progress / progressMax。
    其它 extras 字段变化不改变指纹 → 被当成"内容没变"整条丢弃,流水、详情页、规则全都拿不到新值。
    → 现在任意字段变化都算内容变了(签名覆盖全部 extras)。
  • 防刷屏的 1.2 秒节流此前直接丢弃整条通知。如果一条通知只更新一次
    (比如取件通知从"待取件"变成"已签收"),这次更新恰好落在窗口内就永久消失。
    → 现在节流只压"跑规则 + 执行动作",内容照样就地刷新到那一行:
    不新增行、不跳位置、不计统计、不触发"出现"边沿,动作频率仍是 1.2 秒一次。

刷屏没有回退:同一通知始终只占一行,内容原地更新。

2)正则的正向 / 负向断言"不能用"

根因:Android 的正则引擎是 ICU4C,后行断言里不允许出现无上限量词(* + {n,}),
而桌面 JDK 13+ 已经放开。所以 (?<=取件码[::]?\s*)\d{6} 这类写法在电脑/在线工具上跑得好好的,
到手机上编译直接失败,表现就是"断言不支持"。

修法:新增兼容层 RegexCompat

  • 编译失败时把 (?<=X)P 等价改写成 (?:X)P(仅当 X 含无上限量词),改写结果进缓存;
    对"是否命中"和"按捕获组 $N 取值"完全等价(差别只是 $0 会多含 X 那段文字)。
  • 负向后行 (?<!X) 无法等价改写 → 不改,但给出明确改法。
  • 保存校验、试跑面板不再只说"正则语法有误",而是直接说原因:
    后行断言长度无上限 / 全角符号(( { *)/ \g{n} 等。

仍然成立的一条口径(不是 bug):断言只在单个字段内成立。标题里的「取件」+ 正文里的号码
无法被一个后行断言串起来——请拆成两条规则,或把文字放进捕获组。

安装

notification-filter-v11.4-release.apk · versionCode 14 · Android 8.0+ · 覆盖安装即可(同签名)

  • 签名证书 SHA-256:ECFF994DD1A1BC6E4609088D1CA0F8B8394A63BF6A27C5B70B2FE8D58587D572
  • 文件 SHA-256:b607b5bce0a8c94783927b31d3bc364744e3960778ce8107854a436f7d393a64

验证

450 例单测全绿,新增三组针对本次修复的用例:
RegexCompatTest(断言改写/诊断)、RegexLookaroundTest(四种断言在规则与提取两条链路上都可用)、
ExtrasSignatureTest(任意 extras 变化必须改变指纹;ByteArray 的 identityHash 不参与)。

许可:GPL-3.0(二改后分发须同样开源)。

v11.3 — 修正启动图标(铃舌居中、三横不再被裁)

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 11:24

启动图标修正版。功能与 v11.2 完全相同,只改了图标绘制,已装 v11.2 的可以直接覆盖升级(同一签名,数据保留)。

修了什么

问题 现在
铃舌(小圆)圆心在 x=47,而铃身中心是 54 —— 肉眼可见偏左 圆心归到 54,与铃身同心
右侧三条内容线到 x=90,超出 adaptive icon 半径 36 的安全圆(右端距离圆心 39.4)→ 被启动器圆角/圆形遮罩裁掉,且三条切口不齐 收进 x=76..85、宽 9、圆角 2,y=42/50/58 等距;最远点 33.2 —— 任何遮罩都不会切边

改动文件只有一个:app/src/main/res/drawable/ic_launcher_foreground.xml。

安装

  1. 下载 notification-filter-v11.3-release.apk
  2. 传到手机点击安装(覆盖安装即可,无需卸载)
  3. 若桌面图标没变,长按图标 → 编辑,或重启启动器(部分启动器会缓存图标)
  • 适用:Android 8.0+(minSdk 26)| 包名 com.local.notificationfilter | versionCode 13
  • 签名证书 SHA-256:ECFF994DD1A1BC6E4609088D1CA0F8B8394A63BF6A27C5B70B2FE8D58587D572(与 v11.2 相同)

文件校验

SHA-256: 4f0af80379ee5e5b64e8108ebdb8797f9f531c261cfcebc195223ce53fbee45e

许可

GPL-3.0:二改后分发(发布改过的 APK / 公开代码)必须同样以 GPL-3.0 开源全部源码。

v11.2 — 首个公开发布(Android 通知过滤 App)

Choose a tag to compare

@zmn001125 zmn001125 released this 18 Oct 11:11

Android 通知过滤 App v11.2 —— 首个公开发布版本(侧载 APK)。

安装

  1. 下载下方 notification-filter-v11.2-release.apk
  2. 传到手机后点击安装(系统会提示"未知来源",允许你使用的文件管理器即可)
  3. 打开 App,按首页权限引导授予通知使用权(必须),再打开总开关
  • 适用:Android 8.0 及以上(minSdk 26),在小米 15 / 澎湃 OS3 上开发与验证
  • 包名:com.local.notificationfilter | versionCode 12
  • 签名证书 SHA-256:ECFF994DD1A1BC6E4609088D1CA0F8B8394A63BF6A27C5B70B2FE8D58587D572

文件校验

SHA-256: 00dc204662c30bb45c79456e80c98d589c5e424b1b104a52c705489bd7246747

这一版有什么

  • 规则引擎:7 种匹配模式(全部内容 / 包含任一 / 包含全部 / 不包含任一 / 不包含全部 / 包含 A 且不含 B / 正则)
  • 匹配字段:标题、正文、消息列表、副标题、摘要、发送者 + 通知元信息 + 任意 extras 字段 + media.* 媒体字段
  • 六种动作:消除(可静音渠道)、推迟、替换、朗读、弹幕、悬浮(可叠加,失败留痕)
  • 内容提取:正则抓取,{reN} 当前通知即时提取、{itemsN} 跨通知累积
  • 备份恢复:本地文件夹(SAF)+ 坚果云 WebDAV,支持自动备份与保留策略
  • 通知流水、按天统计、全量搜索、六套主题、App 内使用说明

说明

  • 纯本地运行:不配置 WebDAV 就不会发起任何网络请求,无账号、无埋点、无第三方 SDK
  • 不提供担保,使用风险自负;升级需覆盖安装(同一签名),降级需先卸载(会清空数据,请先备份)
  • 许可:GPL-3.0。二改后分发(发布改过的 APK / 公开代码)必须同样以 GPL-3.0 开源全部源码

完整使用手册见仓库 docs/使用说明.md