鸿蒙6.0应用开发——实现防截屏功能
在鸿蒙(HarmonyOS)系统中,防止截屏和录屏的核心原理与Android类似,都是**在应用窗口层面设置安全属性,由系统图形服务在底层阻止内容捕获**。鸿蒙6.0在此基础上,引入了更智能、主动的安全特性。
·
实现防截屏功能
概述
手机防截屏录屏的意义,远不止于一个简单的“禁止”功能。它的核心在于在数字世界中重新建立“控制”与“边界”,其意义可以从实用保护层和深层影响层两个维度来理解。
| 防护层面 | 防护目标 | 具体意义与场景 |
|---|---|---|
| 个人隐私与数据安全 | 防止敏感信息无意泄露 | 保护手机屏幕上的身份证照片、家庭住址、私密对话、健康记录等。例如,在公共场所展示手机内容时,防截屏功能可以降低被旁人恶意拍照记录的风险。 |
| 高价值数字资产 | 保护虚拟财产与数字凭证 | 防止数字货币钱包地址、密钥、证券交易账户、高价值游戏道具等被截取后用于诈骗或盗取。例如,许多投资APP的交易界面会禁用截屏。 |
| 商业机密与知识产权 | 遏制企业内部信息外泄 | 在企业办公场景中,保护未公开的财务报表、战略规划、设计图纸、源代码、客户名单。确保员工无法通过截屏将机密带离公司可控环境。 |
| 数字内容版权 | 保障付费内容商业模式 | 对于付费课程、独家视频、电子书、订阅制新闻等内容,防止用户通过录屏进行无损盗版和二次传播,保护创作者和平台的收入来源。 |
| 平台秩序与信任 | 维护特定场景的严肃性与安全性 | 在在线考试、金融身份验证、政府/司法远程办理业务等场景,防录屏是防止作弊、伪造和确保流程可信的关键技术环节。 |
在鸿蒙(HarmonyOS)系统中,防止截屏和录屏的核心原理与Android类似,都是在应用窗口层面设置安全属性,由系统图形服务在底层阻止内容捕获。鸿蒙6.0在此基础上,引入了更智能、主动的安全特性。
设置窗口隐私模式,禁止截屏或录屏。此接口适用于禁止截屏/录屏的场景。
页面级防截屏
进入页面开启隐私模式,离开页面取消,具体可参考以下步骤:
首先,在 module.json5 文件中声明需要使用 ohos.permission.PRIVACY_WINDOW 权限。
"requestPermissions": [
{
"name": "ohos.permission.PRIVACY_WINDOW"
}
],
通过导航栏显示状态切换触发 onNavBarStateChange回调。进入页面时,isVisible 为 true,调用setWindowPrivacyMode 设置窗口为隐私模式。离开页面时,isVisible 为 false,设置窗口为非隐私模式。参考示例代码如下:
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
class WindowUtils {
static setWindowPrivacyModeInPage(context: common.UIAbilityContext, isFlag: boolean) {
window.getLastWindow(context).then((lastWindow) => {
lastWindow.setWindowPrivacyMode(isFlag, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to set the window to privacy mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in setting the window to privacy mode.');
});
})
}
}
@Entry
@Component
struct Index {
@State message: string = 'hello world';
@Provide('NavPathStack') pageStack: NavPathStack = new NavPathStack();
context = this.getUIContext();
@Builder
PagesMap(name: string) {
if (name === 'Index') {
Index();
} else if (name === 'PageOne') {
PageOne();
}
}
build() {
Navigation(this.pageStack) {
Column() {
Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })
.width('80%')
.height(40)
.margin(20)
.onClick(() => {
this.pageStack.pushPath({ name: 'PageOne' }) // Push the page info of specified NavDestination into the stack
})
}
}
.navDestination(this.PagesMap)
.onNavBarStateChange((isVisible: boolean) => {
// Callback triggered when navigation bar display state changes
console.info('------>isVisible:' + isVisible)
WindowUtils.setWindowPrivacyModeInPage(this.context.getHostContext() as common.UIAbilityContext, isVisible);
})
}
}
@Component
struct PageOne {
@Consume('NavPathStack') pageStack: NavPathStack;
build() {
NavDestination() {
Column() {
Text('PageOne')
}
}
.title('pageOne')
.onBackPressed(() => {
const popDestinationInfo = this.pageStack.pop(); // Pop the top element from the navigation stack
return true;
})
}
}
代码逻辑走读:
- 导入模块:
- 导入了
BusinessError用于错误处理。 - 导入了
common和window用于UI能力上下文和窗口操作。
- 导入了
- WindowUtils类:
- 定义了一个静态方法
setWindowPrivacyModeInPage,用于在给定的UIAbilityContext中设置窗口的隐私模式。 - 使用
window.getLastWindow(context)获取最后一个窗口。 - 调用
lastWindow.setWindowPrivacyMode(isFlag, callback)设置窗口的隐私模式,并处理回调中的错误。
- 定义了一个静态方法
- Index组件:
- 使用
@Entry和@Component装饰器定义了一个入口组件。 - 定义了状态变量
message和提供者pageStack。 - 定义了一个
PagesMap方法用于根据名称映射页面组件。 - 在
build方法中构建UI,包含一个按钮用于导航到PageOne。 - 使用
onNavBarStateChange监听导航栏的显示状态变化,并在状态变化时调用WindowUtils.setWindowPrivacyModeInPage。
- 使用
- PageOne组件:
- 定义了一个简单的页面组件,显示“PageOne”文本。
- 使用
onBackPressed监听返回键事件,从导航栈中弹出页面。
窗口级防截屏
设置主窗口为隐私模式,参考以下步骤:
在module.json5文件中声明需要使用的ohos.permission.PRIVACY_WINDOW权限。
"requestPermissions": [
{
"name": "ohos.permission.PRIVACY_WINDOW"
}
],
在EntryAbility.ets文件的onWindowStageCreate回调中设置主窗口为隐私模式,具体可参考示例代码:
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// Get the main window
windowStage.getMainWindow((err: BusinessError, data) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
return;
}
let windowClass: window.Window = data;
console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));
// Set the window privacy mode
let isPrivacyMode: boolean = true;
try {
windowClass.setWindowPrivacyMode(isPrivacyMode, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to set the window to privacy mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in setting the window to privacy mode.');
});
} catch (exception) {
console.error('Failed to set the window to privacy mode. Cause:' + JSON.stringify(exception));
}
})
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}
代码逻辑走读:
- 类定义与导入模块:
- 代码首先导入了多个模块,包括
AbilityConstant、ConfigurationConstant、UIAbility、hilog、window和BusinessError。这些模块提供了应用程序生命周期管理、配置常量、UI能力、日志记录和业务错误处理的功能。
- 代码首先导入了多个模块,包括
- 类继承与方法重写:
EntryAbility类继承自UIAbility,并重写了多个方法,如onCreate、onDestroy、onWindowStageCreate、onWindowStageDestroy、onForeground和onBackground。这些方法分别在应用程序的生命周期不同阶段被调用,用于管理应用的状态和窗口。
- 生命周期管理:
- 在
onCreate方法中,设置应用程序的颜色模式,并记录日志信息。 onDestroy方法用于在应用程序销毁时记录日志信息。onWindowStageCreate方法在窗口阶段创建时被调用,获取主窗口并尝试设置其隐私模式,同时加载应用程序内容。onWindowStageDestroy方法在窗口阶段销毁时被调用,用于释放UI相关资源。onForeground和onBackground方法分别在应用程序进入前台和后台时被调用,用于记录日志信息。
- 在
- 错误处理:
- 在获取主窗口和设置窗口隐私模式的过程中,通过检查错误码来处理可能出现的错误,确保应用程序的稳定运行。
- 日志记录:
- 使用
hilog模块记录应用程序的生命周期事件和错误信息,便于开发者进行调试和性能分析。
- 使用
更多推荐




所有评论(0)