在这里插入图片描述

一、前言:Kiosk商用锁机能力定位与落地门槛

鸿蒙7 API26 kioskManager 收敛至@kit.AbilityKit,面向政务一体机、门店收银自助机、景区取票终端、广告触控一体机等企业无人值守商用场景,核心能力是设备开机后锁定单一应用,屏蔽桌面、返回、下拉通知、分屏、设置等所有系统逃逸入口,杜绝客户误操作系统。
该能力属于系统受控企业权限,个人开发者、普通消费手机无法完整使用,完整落地分为「企业资质认证→AGC权限申请→工程开发调试→MDM批量运维→终端上线验收」五大完整流程,本文记录从资质申请到商用终端批量部署全链路实操经验与排坑方案。

二、前置准入资质:开发前必须完成(缺一不可)

2.1 账号资质硬性要求

  1. 华为开发者联盟企业实名认证
    个人账号无权限申请ENTERPRISE_SET_KIOSK受控系统权限,需上传营业执照、法人信息完成企业认证,认证周期1~3个工作日;
  2. 商用终端硬件要求
    设备为鸿蒙商用企业版一体机(政务自助终端、门店触控收银机、广告屏);普通消费手机仅可临时调试API,无法正式商用锁机;模拟器无Kiosk系统服务,完全无法调试;
  3. 业务场景合规材料
    AGC申请权限时需提交商用场景说明文档,包含:终端使用场景、部署地点、无人值守运维方案、防逃逸加固说明,用于平台审核受控权限。

2.2 核心受控权限说明

权限名称:ohos.permission.ENTERPRISE_SET_KIOSK

  1. 权限等级:system_grant(系统受控,无法弹窗动态申请);
  2. 获取渠道:AGC创建应用,发布Profile中勾选该权限并提交商用材料人工审核;
  3. 核心作用:允许应用调用enterKioskMode/exitKioskMode、查询锁机状态、监听锁机变更事件;
  4. 失效场景:使用DevEco自动调试签名、个人账号Profile、未勾选权限的签名包,调用API直接抛出权限不足报错。

2.3 完整前置资质办理四步流程

  1. 注册华为开发者联盟账号,完成企业实名认证;
  2. AGC创建对应商用应用,进入「发布-签名Profile」页面,新建发布Profile;
  3. 权限列表勾选ohos.permission.ENTERPRISE_SET_KIOSK,上传自助终端商用场景说明材料提交审核;
  4. 审核通过后下载带权限的p7b签名Profile、p12证书,工程全程使用该企业正式签名。

三、工程全量配置(module.json5 权限、自启、窗口锁机配套)

3.1 权限与窗口、自启动完整配置

{
  "module": {
    "name": "entry",
    "deviceTypes": ["tablet"],
    "requestPermissions": [
      {
        "name": "ohos.permission.ENTERPRISE_SET_KIOSK",
        "reason": "$string:kiosk_lock_terminal",
        "usedScene": { "abilities": ["EntryAbility"], "when": "always" }
      },
      {
        "name": "ohos.permission.WINDOW_FULLSCREEN",
        "reason": "$string:fullscreen_hide_system_bar",
        "usedScene": { "abilities": ["EntryAbility"], "when": "always" }
      }
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "exported": true,
        "launchType": "singleTask",
        "window": {
          "autoHiddenNavigationBar": true,
          "autoHiddenStatusBar": true,
          "designWidth": 720
        },
        "metadata": [
          // 开机上电自动启动应用(商用终端核心配置)
          {
            "name": "ohos.ability.startup",
            "value": "auto_start"
          }
        ]
      }
    ]
  }
}

3.2 @kit标准导入依赖

"dependencies": {
  "@kit.AbilityKit": "1.0.0",
  "@kit.ArkUI": "1.0.0",
  "@kit.PerformanceAnalysisKit": "1.0.0",
  "@kit.BasicServicesKit": "1.0.0"
}

四、分层开发完整业务代码

4.1 第一层:EntryAbility 生命周期自动上锁、全屏隐藏系统UI

核心逻辑:窗口创建时全屏透明隐藏状态栏/导航栏;应用切前台自动校验并重新进入Kiosk锁机,防止后台回收后解锁逃逸。

import { UIAbility, Want, window, kioskManager, common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "KioskEntryAbility";
const DOMAIN = 0x0015;

export default class EntryAbility extends UIAbility {
  private uiContext: common.UIAbilityContext | null = null;

  onCreate(want: Want, launchParam: common.LaunchParam): void {
    this.uiContext = this.context as common.UIAbilityContext;
    hilog.info(DOMAIN, TAG, "商用Kiosk自助终端应用启动");
  }

  // 窗口创建:全屏隐藏系统状态栏、导航栏,杜绝下拉逃逸手势
  onWindowStageCreate(windowStage: window.WindowStage): void {
    const mainWin = windowStage.getMainWindow();
    mainWin.then(win => {
      // 开启全屏布局
      win.setWindowLayoutFullScreen(true);
      // 系统栏完全透明隐藏,无任何可触发下拉的UI区域
      win.setWindowSystemBarProperties({
        statusBarOpacity: 0,
        navigationBarOpacity: 0,
        statusBarBackgroundColor: "#00000000",
        navigationBarBackgroundColor: "#00000000"
      });
    });
    // 加载自助业务页面
    windowStage.loadContent("pages/KioskIndexPage", (err) => {
      if (err.code) hilog.error(DOMAIN, TAG, `页面加载失败:${err.message}`);
    });
  }

  // 应用切前台,自动重锁(兜底核心逻辑)
  onForeground(): void {
    this.autoEnterKioskLock();
  }

  // 自动校验并进入商用单应用锁定模式
  private async autoEnterKioskLock() {
    if (!this.uiContext) return;
    try {
      const lockStatus = kioskManager.getKioskStatus();
      // 已为本应用锁定,无需重复执行
      if (lockStatus.isKioskMode && lockStatus.kioskBundleName === this.uiContext.bundleName) {
        hilog.info(DOMAIN, TAG, "当前已处于Kiosk锁定模式");
        return;
      }
      // 执行进入锁机模式
      await kioskManager.enterKioskMode(this.uiContext);
      hilog.info(DOMAIN, TAG, "成功进入商用终端单应用锁定");
    } catch (err) {
      const e = err as BusinessError;
      // 错误码160001:设备已有其他Kiosk应用锁定,需先退出原有锁机
      if (e.code === 160001) {
        hilog.error(DOMAIN, TAG, "设备存在其他锁定应用,无法进入锁机");
      } else {
        hilog.error(DOMAIN, TAG, `进入Kiosk失败 code:${e.code} msg:${e.message}`);
      }
    }
  }

  onBackground(): void {
    // 注销锁机状态监听,防止内存泄漏
    kioskManager.off("kioskChange");
  }
}

4.2 第二层:业务主页面(客户业务区+管理员密码退出锁机)

页面分为两块:客户自助业务操作区(无退出入口)、隐藏管理员密码面板(运维专用,输入密码才可调用exitKioskMode退出锁机),搭配ArkUI V2状态实时展示锁机状态。
在这里插入图片描述

import { ComponentV2, Local } from '@kit.ArkUI';
import { kioskManager, common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "KioskBusinessPage";
// 生产环境:密码通过SecurityKit加密存储,禁止硬编码
const ADMIN_PASSWORD = "kiosk_admin_2026";

@Entry
@ComponentV2
struct KioskIndexPage {
  @Local isLockActive: boolean = false;
  @Local inputPwd: string = "";
  @Local tipMsg: string = "商用自助终端 · 已启用Kiosk锁定,客户无法退出";
  private uiCtx: common.UIAbilityContext | null = null;

  aboutToAppear() {
    this.uiCtx = getContext(this) as common.UIAbilityContext;
    this.refreshLockStatus();
    // 监听锁机状态变更事件
    kioskManager.on("kioskChange", () => {
      this.refreshLockStatus();
    });
  }

  aboutToDisappear() {
    kioskManager.off("kioskChange");
  }

  // 实时刷新当前锁机状态
  private refreshLockStatus() {
    const status = kioskManager.getKioskStatus();
    this.isLockActive = status.isKioskMode;
    if (this.isLockActive) {
      this.tipMsg = `锁定生效,当前锁定应用:${status.kioskBundleName}`;
    } else {
      this.tipMsg = "未进入Kiosk商用锁定模式";
    }
  }

  // 管理员密码校验,退出锁机模式
  private async exitLockMode() {
    if (this.inputPwd !== ADMIN_PASSWORD) {
      this.tipMsg = "管理员密码错误,禁止退出锁机";
      return;
    }
    if (!this.uiCtx) return;
    try {
      await kioskManager.exitKioskMode(this.uiCtx);
      this.tipMsg = "已成功退出Kiosk锁机模式,可进入系统设置运维";
      this.inputPwd = "";
    } catch (err) {
      const e = err as BusinessError;
      this.tipMsg = `退出锁机失败:${e.message}`;
      hilog.error(0x0015, TAG, `退出Kiosk异常:${JSON.stringify(err)}`);
    }
  }

  build() {
    Column({ space: 30 }) {
      Text("政务/门店商用自助终端 Kiosk 锁机系统")
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40 });

      Text(this.tipMsg)
        .fontSize(16)
        .fontColor(this.isLockActive ? "#00B42A" : "#F53F3F");

      // ========== 客户业务操作区(无任何退出、系统入口) ==========
      Column() {
        Text("客户业务办理区域")
          .fontSize(22)
          .margin({ bottom: 20 });
        Flex({ wrap: FlexWrap.Wrap, gap: 20 }) {
          Button("业务查询").width(180).height(50).backgroundColor("#0A59F7");
          Button("凭证打印").width(180).height(50).backgroundColor("#0A59F7");
          Button("业务办理").width(180).height(50).backgroundColor("#0A59F7");
        }
      }
      .width("90%")
      .height(240)
      .padding(24)
      .backgroundColor("#F5F7FA")
      .borderRadius(12);

      // ========== 管理员运维退出面板(线下隐藏,仅运维使用) ==========
      Column({ space: 12 }) {
        Text("管理员运维入口(仅内部人员使用)")
          .fontSize(14)
          .fontColor("#666666");
        TextInput({ text: this.inputPwd })
          .width("90%")
          .height(44)
          .type(InputType.Password)
          .onChange(v => this.inputPwd = v);
        Button("验证密码,退出锁机模式")
          .width("90%")
          .height(48)
          .backgroundColor("#F53F3F")
          .onClick(() => this.exitLockMode());
      }
      .width("90%")
      .padding(16)
      .backgroundColor("#FFFFFF")
      .borderRadius(12);

      Blank();
      Text("💡 锁机生效后:下拉通知栏、返回手势、分屏、桌面全部屏蔽,客户无法逃逸")
        .fontSize(12)
        .fontColor("#888888")
        .margin({ bottom: 40 });
    }
    .width("100%")
    .height("100%")
    .backgroundColor("#F8F9FA");
  }
}

五、多层商用终端加固方案(仅Kiosk锁机存在逃逸漏洞,四层防护杜绝客户越狱)

加固1:开机自动拉起应用

配置ohos.ability.startup:auto_start,设备断电重启后无需人工操作,自动启动应用并进入锁机,适配7×24小时无人值守场景。

加固2:窗口全屏+透明系统栏

窗口阶段强制隐藏状态栏、导航栏,无任何可触发下拉控制中心的UI区域,从视觉上屏蔽系统入口。

加固3:前台自动重锁兜底

onForeground生命周期自动执行上锁逻辑,应用被系统后台回收、进程异常重启后,切前台立刻重新锁定,防止短暂解锁逃逸。

加固4:企业MDM设备管理平台高阶管控(批量商用必备)

搭配华为HEM设备管理平台,实现终端深度管控:

  1. 禁用USB调试、文件传输、安装第三方应用;
  2. 屏蔽系统设置、应用市场、浏览器、快捷关机入口;
  3. 远程下发指令一键进入/退出Kiosk锁机,无需现场输入管理员密码;
  4. 批量同步应用、推送日志、远程重启终端,减少线下运维成本。

六、完整调试、打包、上线部署流程

  1. AGC权限审核:企业账号提交带Kiosk权限的Profile申请,1~3个工作日完成人工审核;
  2. 工程配置企业正式签名:DevEco Studio导入p12证书、审核通过的p7b Profile,关闭自动调试签名;
  3. 真机调试:仅鸿蒙商用企业版一体机支持,普通消费手机、模拟器均无法调用Kiosk受控API;
  4. Release商用包打包:Build -> Build Hap(s),输出带完整权限的HAP安装包;
  5. 终端批量部署
    • 单台终端:USB安装HAP,上电自动启动锁机;
    • 多门店批量:接入HEM MDM平台,远程批量下发安装、管控锁机状态;
  6. 全场景验收测试:折叠开合、下拉通知、返回手势、分屏、长按电源键全部验证,确认无系统逃逸入口。

七、高频商用开发踩坑完整排坑手册

坑1:enterKioskMode 调用提示权限不足

  1. 使用个人开发者账号,无企业资质;
  2. AGC签名Profile未勾选ohos.permission.ENTERPRISE_SET_KIOSK受控权限;
  3. 使用IDE自动调试签名,仅正式企业签名携带系统受控权限;
  4. module.json5未声明对应权限字段。

坑2:错误码160001:设备已存在其他Kiosk应用

同一台商用终端同一时间仅允许一个应用锁定,需要先执行另一款应用exitKioskMode退出锁机,当前应用才能进入锁定模式。

坑3:应用后台被杀后,锁机自动失效

兜底方案:

  1. 配置launchType:singleTask单实例启动;
  2. onForeground生命周期强制重新执行自动上锁逻辑;
  3. 搭配MDM平台开启应用保活策略,减少系统回收概率。

坑4:下拉手势、分屏窗口仍能调出系统UI

  1. 设备为普通消费版鸿蒙系统,底层管控能力受限;
  2. 窗口未配置autoHiddenNavigationBar/autoHiddenStatusBar自动隐藏系统栏;
  3. 未开启全屏布局,状态栏存在可下拉触发区域。

坑5:退出锁机后系统导航栏、状态栏不恢复

解决方案:调用exitKioskMode后,重置窗口系统栏属性,或重启应用恢复默认窗口样式。

坑6:普通手机、模拟器无法调试Kiosk API

底层系统限制:ENTERPRISE_SET_KIOSK受控权限仅对企业商用终端、MDM管控设备开放,个人手机、模拟器无权限调用相关接口。

坑7:管理员密码硬编码存在安全漏洞

生产规范:禁止明文写死密码,使用SecurityKit HUKS密钥加密存储,支持MDM后台远程动态修改运维密码。

八、商用生产环境最佳实践

  1. 操作日志全链路审计
    Kiosk进入、退出、管理员密码验证、远程运维指令全部写入系统hilog日志,操作行为可追溯;
  2. UI分层隔离
    客户操作区与管理员密码面板视觉隔离,线下终端可隐藏密码输入区域,杜绝普通客户看到退出入口;
  3. 异常兜底机制
    所有锁机API增加try-catch捕获异常,锁机失败给出运维提示,不直接闪退应用;
  4. 批量运维标准化
    多门店、多终端统一接入HEM MDM平台,远程一键切换锁机状态、推送更新、收集终端日志;
  5. 断电防护
    开机自启动配置保证断电重启自动恢复锁定,无需人工现场操作;
  6. 隐私安全加固
    管理员密码、业务敏感数据全部通过SecurityKit HUKS密钥托管,禁止明文存储;
  7. 多形态兼容
    商用折叠触控一体机,可叠加FoldSplitContainer悬停布局,锁机模式下折叠适配功能正常生效。

九、完整落地总结

鸿蒙7商用Kiosk锁机应用完整落地分为企业资质认证→AGC受控权限申请→工程配置分层开发→四层终端加固→MDM批量运维上线完整流程,核心依赖企业受控系统权限实现单应用完全锁定,屏蔽全部系统逃逸入口。
该方案专门面向线下门店收银、政务自助、景区取票、广告触控一体机等无人值守商用场景,开发核心要点是「前台自动重锁兜底、全屏隐藏系统UI、管理员密码管控退出、MDM远程运维」四层防护,彻底解决商用终端客户误操作系统、随意退出业务应用的痛点,是鸿蒙企业级商用终端标准化开发方案。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐