鸿蒙防窥能力适合接到哪些业务页面,不适合哪些页面
适合谁看
想判断鸿蒙防窥能力落点的人
做内容型、工具型、隐私型页面设计的人
不想为了展示能力而牺牲体验的人
问题背景
系统能力一旦接进项目,大家很容易出现两个极端:
什么页面都不接
什么页面都接
真正合理的做法,是让能力只出现在它真正有价值的页面。
项目中的真实场景
食界探味当前的防窥命名已经给了一个很强的信号:
// anti_peep_protection_channel.dart static Future<void> activateCollectionProtection() async { await _invoke('activateCollectionProtection'); } static Future<void> deactivateCollectionProtection() async { await _invoke('deactivateCollectionProtection'); }方法名里的Collection说明它优先面向收藏页。
激活时机在app.dart的底部导航栏管理中:
_scheduleCollectionProtectionSync( isLoggedIn && widget.navigationShell.currentIndex == 2, // index 2 = 收藏页 );只有用户切到收藏页(index 2)且已登录时才激活防窥。
核心实现
一、适合接入防窥的页面
页面 | 为什么适合 | 防窥价值 |
|---|---|---|
收藏页 | 展示用户收藏的菜品,暴露个人口味偏好 | 高 |
心愿单页 | 展示用户"想吃"的菜品,暴露个人兴趣 | 高 |
个人资料页 | 展示用户名、头像、个人设置 | 中高 |
订单/历史页 | 展示用户消费记录 | 高 |
AI 对话历史 | 展示用户和 AI 的对话内容 | 中高 |
这些页面的共同特点:内容和个人身份、偏好、消费行为强关联。被旁人看到可能造成真实困扰。
食界探味当前选择收藏页作为防窥对象,原因很明确:
收藏页的内容: - 用户收藏了哪些菜品 → 暴露口味偏好 - 用户喜欢哪个国家的菜 → 暴露饮食习惯 - 用户收藏的频率和时间 → 暴露生活规律 被旁人看到的后果: - "你怎么收藏了这么多日料" → 尴尬 - "你居然喜欢这个" → 隐私暴露二、不适合接入防窥的页面
页面 | 为什么不适合 | 防窥价值 |
|---|---|---|
首页/探索页 | 公共推荐内容,和个人无关 | 无 |
搜索页 | 搜索结果是公共数据 | 无 |
菜品详情页 | 展示的是公共菜品信息 | 无 |
食材列表页 | 公共食材数据 | 无 |
风味地图页 | 公共地理数据 | 无 |
关于页/设置页 | 不涉及个人数据 | 无 |
这些页面即使不开防窥,实际风险也不高。如果强行开启,反而会:
打断用户浏览公共内容的体验
增加不必要的系统开销
让用户困惑"为什么看个菜谱还要防窥"
三、判断框架——3 个问题
判断一个页面是否适合接入防窥,问自己 3 个问题:
问题 | 是 → 适合 | 否 → 不适合 |
|---|---|---|
这里展示的内容是否明显带有用户偏好? | 适合 | 不适合 |
被旁人看到会不会造成真实困扰? | 适合 | 不适合 |
开启防窥后会不会明显打断主要操作? | 不适合 | 适合 |
三个条件需要同时满足前两个"是",且第三个"否",才值得接。
用这个框架检验食界探味的收藏页:
问题 | 收藏页 | 探索页 |
|---|---|---|
内容带有用户偏好? | ✅ 是 | ❌ 否 |
被看到有困扰? | ✅ 是 | ❌ 否 |
会打断操作? | ❌ 否(只是隐藏内容) | ❌ 否 |
结论 | ✅ 适合 | ❌ 不适合 |
四、食界探味的页面分析
食界探味当前的主要页面:
页面 | Tab | 个人数据 | 防窥适合度 |
|---|---|---|---|
探索页 | 首页 | 无 | ❌ 不适合 |
灵感页 | Tab 2 | 无 | ❌ 不适合 |
收藏页 | Tab 3 | 有(收藏的菜品) | ✅ 适合 |
我的页 | Tab 4 | 有(个人资料) | ⚠️ 可考虑 |
AI 助手页 | 独立页 | 有(对话历史) | ⚠️ 可考虑 |
搜索页 | 独立页 | 无 | ❌ 不适合 |
菜品详情页 | 独立页 | 无 | ❌ 不适合 |
食材详情页 | 独立页 | 无 | ❌ 不适合 |
当前只在收藏页激活防窥,这是一个合理的起点。未来可以考虑扩展到 AI 助手页(对话历史可能暴露用户兴趣)。
五、为什么不应该全局开启
全局开启防窥的问题:
问题 | 说明 |
|---|---|
体验断裂 | 用户看个菜谱都要被遮罩,体验很差 |
系统开销 | 鸿蒙一直监听防窥事件,浪费资源 |
用户困惑 | "为什么这个页面也要防窥?" |
误触发 | 公共内容被遮罩,用户以为 app 出 bug 了 |
比赛扣分 | 评委看到全局防窥会质疑产品判断力 |
六、防窥的激活时机设计
食界探味的激活时机设计:
// app.dart → _ScaffoldWithNavBarState void _scheduleCollectionProtectionSync(bool shouldProtect) { if (_lastCollectionProtectionTarget == shouldProtect) return; _lastCollectionProtectionTarget = shouldProtect; WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; if (shouldProtect) { AntiPeepProtectionChannel.activateCollectionProtection(); } else { AntiPeepProtectionChannel.deactivateCollectionProtection(); } }); }调用时机:
用户切 Tab │ ├─ currentIndex == 2(收藏页)→ activate ├─ currentIndex != 2 → deactivate │ ▼ 页面退出 │ └─ dispose() → deactivate(确保取消)这个设计保证了:
只在收藏页时激活,其他页面不激活
切走时立即取消,不残留
退出时兜底取消,不泄漏
七、防窥和页面体验的平衡
防窥保护会增加一层"被监控感"。所以在设计时需要平衡:
维度 | 好的设计 | 差的设计 |
|---|---|---|
激活范围 | 只在敏感页面 | 全局所有页面 |
用户感知 | 自然,无感 | 突然出现蒙层 |
退出处理 | 切走即取消 | 需要手动关闭 |
内容处理 | 隐藏敏感内容 | 遮住整个屏幕 |
系统提示 | 不打扰用户 | 弹窗提醒"已开启防窥" |
食界探味当前的做法是"进入收藏页自动激活,离开自动取消",用户完全无感。这是最好的体验。
八、如果要扩展到更多页面
如果以后要在更多页面接入防窥,建议:
按敏感度分级— 收藏页 > AI 对话 > 个人资料 > 其他
渐进式扩展— 先收藏页,验证效果后再扩展
保持按需激活— 永远不要全局常驻
页面级控制— 每个页面自己决定是否需要防窥
关键代码位置
文件 | 作用 |
|---|---|
| 防窥通道 |
| 页面级激活/取消防窥 |
| 鸿蒙原生插件 |
常见坑
为了展示能力,对所有页面全局开启— 体验断裂,评委质疑
只从比赛展示角度判断,不从用户场景判断— 用户不需要看菜谱时防窥
页面敏感度其实不高,却引入了额外交互打扰— 公共内容不需要防窥
没有退出页面后的关闭逻辑— 防窥残留,影响后续页面
没有检查用户是否已登录— 未登录时没有个人数据,不需要防窥
防窥和页面动画冲突— 蒙层出现时页面正在转场,体验差
可复用模板
页面防窥判断模板
判断页面是否需要防窥: □ 内容是否带有用户偏好/个人数据? □ 被旁人看到是否造成真实困扰? □ 开启后是否打断主要操作? □ 用户是否有明确的隐私预期? 4 个"是"→ 适合 3 个"是"→ 考虑 2 个及以下 → 不适合页面级防窥激活模板
class SensitivePage extends StatefulWidget { @override State<SensitivePage> createState() => _SensitivePageState(); } class _SensitivePageState extends State<SensitivePage> { @override void initState() { super.initState(); AntiPeepProtectionChannel.activateCollectionProtection(); } @override void dispose() { AntiPeepProtectionChannel.deactivateCollectionProtection(); super.dispose(); } @override Widget build(BuildContext context) { return ValueListenableBuilder<AntiPeepVisibilityState>( valueListenable: AntiPeepProtectionChannel.visibilityState, builder: (context, state, child) { if (state == AntiPeepVisibilityState.hidden) { return const SafePlaceholder(); } return child!; }, child: const SensitiveContent(), ); } }Tab 级防窥激活模板
// 根据当前 Tab 决定是否激活 void syncProtection(int currentIndex) { final shouldProtect = currentIndex == SENSITIVE_TAB_INDEX; if (shouldProtect) { AntiPeepProtectionChannel.activateCollectionProtection(); } else { AntiPeepProtectionChannel.deactivateCollectionProtection(); } }本篇总结
防窥能力应该按页面价值接入,而不是按"能接就接"。核心判断标准:
内容敏感度— 是否带有用户偏好和个人数据
暴露后果— 被旁人看到是否造成困扰
体验影响— 开启后是否打断主要操作
食界探味当前只在收藏页激活防窥,是因为收藏页是整个 app 中个人数据最集中、隐私敏感度最高的页面。探索页、搜索页、详情页都是公共内容,不需要防窥。
对系统能力做业务筛选,本身就是成熟项目的一部分。"能接"不代表"该接",选择在哪里接、不在哪里接,体现的是产品判断力。
