在鸿蒙元服务开发中,屏幕相关能力往往直接影响用户体验。比如视频播放时需要保持亮屏、阅读场景需要调节亮度、金融类服务需要防止截屏泄露信息。ASCF(Ability Service Collaboration Framework)针对这些场景提供了6个屏幕API,覆盖亮度控制、常亮设置、截屏监听和防截屏,接口形式简洁,上手成本很低。本文基于实际开发经验,梳理这些API的用法、典型场景以及容易踩的坑。
一、亮度控制:设置与获取
亮度控制有两个接口:setScreenBrightness用于设置亮度,getScreenBrightness用于获取当前亮度。设置时value的取值范围是0到1,0最暗,1最亮。如果传入-1,则恢复为跟随系统亮度。
- // 设置亮度为50%
- has.setScreenBrightness({
- value: 0.5,
- success: () => {
- console.info('亮度设置成功');
- },
- fail: (err) => {
- console.error('亮度设置失败:', err);
- }
- });
- // 恢复系统亮度
- has.setScreenBrightness({
- value: -1,
- success: () => {
- console.info('已恢复系统亮度');
- }
- });
复制代码
获取当前亮度时,如果返回值是-1,说明当前亮度跟随系统,而不是一个具体的数值。代码里需要对这个特殊值做判断,避免直接用0-1的逻辑处理。
- has.getScreenBrightness({
- success: (res) => {
- console.info('当前亮度:', res.value);
- // value 范围 0-1,-1 表示跟随系统
- },
- fail: (err) => {
- console.error('获取亮度失败:', err);
- }
- });
复制代码
一个典型场景是阅读模式。进入阅读模式时,先保存当前亮度,再把亮度调到0.3;退出时恢复之前保存的亮度。实现逻辑如下:
- Page({
- data: {
- isReadingMode: false,
- originalBrightness: -1,
- },
- toggleReadingMode() {
- let that = this;
- if (that.data.isReadingMode) {
- // 退出阅读模式,恢复亮度
- has.setScreenBrightness({
- value: -1,
- success: () => {
- that.setData({ isReadingMode: false });
- has.showToast({ title: '已退出阅读模式' });
- }
- });
- } else {
- // 先保存当前亮度
- has.getScreenBrightness({
- success: (res) => {
- that.setData({ originalBrightness: res.value });
- // 设置低亮度
- has.setScreenBrightness({
- value: 0.3,
- success: () => {
- that.setData({ isReadingMode: true });
- has.showToast({ title: '已进入阅读模式' });
- }
- });
- }
- });
- }
- }
- });
复制代码
注意:setScreenBrightness设置的亮度只在当前元服务内生效,切到其他应用或回到桌面后会自动恢复系统亮度,无法全局改变系统亮度。如果需要全局调节,应使用系统能力@ohos.brightness。
二、屏幕常亮:setKeepScreenOn
setKeepScreenOn用于控制屏幕是否保持常亮。参数keepScreenOn为true时开启,false时关闭。接口本身很简单,但要注意生命周期管理。
- // 开启常亮
- has.setKeepScreenOn({
- keepScreenOn: true,
- success: () => {
- console.info('屏幕常亮已开启');
- },
- fail: (err) => {
- console.error('设置失败:', err);
- }
- });
- // 关闭常亮
- has.setKeepScreenOn({
- keepScreenOn: false,
- success: () => {
- console.info('屏幕常亮已关闭');
- }
- });
复制代码
最典型的场景是视频播放。播放时开启常亮,暂停时关闭,页面销毁时也要记得关闭,避免异常退出导致亮屏状态残留。
- Page({
- data: {
- isPlaying: false,
- },
- onVideoPlay() {
- this.setData({ isPlaying: true });
- has.setKeepScreenOn({ keepScreenOn: true });
- },
- onVideoPause() {
- this.setData({ isPlaying: false });
- has.setKeepScreenOn({ keepScreenOn: false });
- },
- onUnload() {
- // 页面销毁时关闭常亮
- has.setKeepScreenOn({ keepScreenOn: false });
- }
- });
复制代码
导航场景也常用常亮。导航页面在onShow时开启常亮,onHide时关闭,保证用户在不触碰屏幕时也能持续看到路线。
- Page({
- onShow() {
- // 导航页面开启常亮
- has.setKeepScreenOn({
- keepScreenOn: true,
- success: () => {
- console.info('导航模式:屏幕常亮');
- }
- });
- },
- onHide() {
- // 页面隐藏时关闭常亮
- has.setKeepScreenOn({ keepScreenOn: false });
- }
- });
复制代码
和亮度设置一样,常亮设置也是临时的,只在当前元服务内有效。用户退出元服务后,屏幕会恢复正常熄屏策略,这是系统保护机制,不是Bug。
三、截屏监听:onUserCaptureScreen
ASCF提供onUserCaptureScreen来监听用户截屏行为,offUserCaptureScreen用于移除监听。注册回调后,只要用户触发系统截屏,回调就会执行。
- // 注册截屏监听
- const onCapture = function() {
- console.info('用户截屏了');
- // 可以在这里做安全提示
- };
- has.onUserCaptureScreen(onCapture);
- // 移除监听
- has.offUserCaptureScreen(onCapture);
复制代码
需要注意,onUserCaptureScreen只能注册一个监听函数。如果重复注册,后面的回调会覆盖之前的,所以建议在页面级别统一管理,避免多个模块互相干扰。
实际场景中,截屏监听常用于安全提示。比如金融类页面或私密聊天页面,用户截屏后立即弹出一条警示,提示“截屏已记录”。实现时可以在onReady注册监听,在onUnload移除。
- Page({
- data: {
- showCaptureWarning: false,
- },
- onReady() {
- let that = this;
- has.onUserCaptureScreen(function() {
- that.setData({ showCaptureWarning: true });
- setTimeout(() => {
- that.setData({ showCaptureWarning: false });
- }, 3000);
- });
- },
- onUnload() {
- has.offUserCaptureScreen();
- }
- });
复制代码
四、防截屏/录屏:setVisualEffectOnCapture
如果希望在截屏或录屏时隐藏敏感内容,可以使用setVisualEffectOnCapture。将visualEffect设为hidden,窗口在截屏/录屏时会被替换为黑色画面,从而保护隐私。设为none则恢复正常。
- // 开启防截屏
- has.setVisualEffectOnCapture({
- visualEffect: 'hidden', // 截屏时隐藏
- success: () => {
- console.info('防截屏已开启');
- },
- fail: (err) => {
- console.error('设置失败:', err);
- }
- });
- // 关闭防截屏
- has.setVisualEffectOnCapture({
- visualEffect: 'none',
- success: () => {
- console.info('防截屏已关闭');
- }
- });
复制代码
这个API有两个明显的限制:一是起始版本为2.0.1,比其他屏幕API晚很多,做功能规划时必须考虑低版本兼容;二是需要ohos.permission.PRIVACY_WINDOW权限,而且这个权限需要在AGC(AppGallery Connect)平台申请,不是普通声明就能拿到。
五、踩坑总结与API速查
根据实际使用经验,以下问题值得注意:
1. setScreenBrightness设置的亮度只在当前元服务内有效,不能依赖它做全局亮度调节。
2. setKeepScreenOn同样只作用于当前元服务,用户退出后自动恢复熄屏策略。页面销毁时最好主动关闭,养成好习惯。
3. onUserCaptureScreen只能注册一个监听函数,重复注册会覆盖。建议在页面级统一注册和移除。
4. setVisualEffectOnCapture版本要求高(2.0.1起),且需要申请PRIVACY_WINDOW权限。对金融、密码管理等强隐私场景是刚需,但要做好版本降级方案。
5. getScreenBrightness返回-1表示跟随系统设置,需要做特殊处理。
最后给出API速查表:
- 设置亮度:has.setScreenBrightness({ value });value为0-1,-1恢复系统。
- 获取亮度:has.getScreenBrightness({ success(res) });res.value为0-1或-1。
- 开启/关闭常亮:has.setKeepScreenOn({ keepScreenOn });布尔值控制。
- 截屏监听:has.onUserCaptureScreen(callback) / has.offUserCaptureScreen(callback)。
- 防截屏:has.setVisualEffectOnCapture({ visualEffect: 'hidden' | 'none' })。
ASCF的屏幕API虽然能力有限,但胜在简单直接,覆盖了亮度、常亮、截屏三个高频维度。阅读类、视频类、导航类元服务可以直接使用;防截屏能力则更适合对安全要求较高的应用。如果业务需要更底层的系统级控制,可以关注@ohos.brightness等系统模块,但那些接口的权限和复杂度会明显更高。当前API的临时生效机制虽然限制了灵活性,但也避免了元服务随意改动用户系统设置,是一种合理的设计取舍。 |