鸿蒙7新特性实战⑧:商用Kiosk锁定应用完整开发流程(API26 自助终端/门店一体机)

前言

Kiosk(商用自助锁定模式)是鸿蒙面向门店收银机、自助取票机、政务终端、广告一体机的企业级管控能力,核心作用:
设备开机后仅运行当前应用,屏蔽返回键、Home桌面、下拉通知栏、多任务、分屏、设置入口,用户无法退出应用、切换其他程序,防止客户误操作系统。
API26(鸿蒙7)kioskManager统一收敛至@kit.AbilityKit,属于企业受限系统权限,普通个人应用无法使用,必须企业开发者认证+AGC申请受控权限Profile。

一、核心前置门槛(开发前必须完成,否则API直接报错)

1.1 账号资质要求

  1. 华为开发者联盟企业实名认证,个人账号无权限申请Kiosk管控权限;
  2. 设备为鸿蒙企业版/商用自助终端(普通消费手机仅调试,无法正式商用锁机);
  3. 应用归属企业商用场景(自助终端、政务、零售门店),上架审核需提供商用场景说明材料。

1.2 关键受限权限说明

核心权限:ohos.permission.ENTERPRISE_SET_KIOSK

  • 权限等级:system_grant 系统受控权限,不能动态弹窗申请
  • 获取方式:AGC创建发布Profile时勾选该权限,审核通过后下载签名Profile打包;
  • 作用:允许应用进入/退出Kiosk单应用锁定模式、查询锁机状态。

1.3 完整前置流程(四步)

  1. 企业账号完成认证;
  2. AGC创建应用,申请发布Profile,勾选ENTERPRISE_SET_KIOSK并提交商用场景说明;
  3. 下载带权限的签名p7b Profile、证书;
  4. 工程配置正式企业签名,调试/打包均使用该签名,自动签名无受控权限无法调用Kiosk API。

二、工程配置全量代码

2.1 module.json5 权限、窗口、自启配置

{ "module": { "name": "entry", "type": "har", "deviceTypes": ["tablet", "phone"], "requestPermissions": [ { "name": "ohos.permission.ENTERPRISE_SET_KIOSK", "reason": "$string:kiosk_lock_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } }, // 全屏、窗口管控配套权限 { "name": "ohos.permission.WINDOW_FULLSCREEN", "reason": "$string:fullscreen_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } } ], "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "exported": true, "launchType": "singleTask", "skills": [], "metadata": [ // 开机自启动(商用终端必备) { "name": "ohos.ability.startup", "value": "auto_start" } ], "window": { "designWidth": 720, "autoHiddenNavigationBar": true, "autoHiddenStatusBar": true } } ] } }

2.2 oh-package.json5 标准@kit导入依赖

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

三、Kiosk核心API能力总览(@kit.AbilityKit.kioskManager)

API作用
enterKioskMode(context)进入单应用锁定模式,屏蔽所有系统逃逸入口
exitKioskMode(context)退出锁机(管理员密码/后台运维使用)
getKioskStatus()查询当前锁机状态:是否锁定、锁定应用包名
on("kioskChange", callback)监听锁机状态变更(被强制退出、系统切换)

锁机后系统自动限制效果

  1. 屏蔽底部虚拟导航栏(返回、主页、多任务键消失);
  2. 顶部状态栏/通知栏下拉手势拦截,无法调出控制中心;
  3. Home键、多任务手势失效,无法返回桌面;
  4. 分屏、悬浮窗、自由窗口全部禁用;
  5. 其他应用无法前台拉起,系统仅保留当前应用进程;
  6. 屏蔽系统设置快捷入口、下拉菜单关机/重启选项。

四、完整分层实战代码

4.1 第一层:EntryAbility 生命周期自动进锁+全屏隐藏系统栏

应用切前台自动校验并进入Kiosk,页面加载前设置全屏无系统UI:

import{UIAbility,Want,window,kioskManager,common}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{BusinessError}from'@kit.BasicServicesKit';constTAG="KioskAbility";constDOMAIN=0x0005;exportdefaultclassEntryAbilityextendsUIAbility{uiContext:common.UIAbilityContext|null=null;onCreate(want:Want,launchParam:common.LaunchParam):void{this.uiContext=this.contextascommon.UIAbilityContext;hilog.info(DOMAIN,TAG,"商用Kiosk应用启动");}// 窗口创建,全屏隐藏状态栏、导航栏onWindowStageCreate(windowStage:window.WindowStage):void{constmainWin=windowStage.getMainWindow();mainWin.then(win=>{// 全屏模式win.setWindowLayoutFullScreen(true);// 透明系统栏,彻底隐藏win.setWindowSystemBarProperties({statusBarOpacity:0,navigationBarOpacity:0,statusBarBackgroundColor:"#00000000",navigationBarBackgroundColor:"#00000000"});});// 加载业务页面windowStage.loadContent("pages/KioskIndex",(err)=>{if(err.code)hilog.error(DOMAIN,TAG,`页面加载失败:${err.message}`);});}// 切前台自动进入锁机模式(核心)onForeground():void{this.autoEnterKiosk();}// 自动校验并进入Kiosk锁定privateasyncautoEnterKiosk(){if(!this.uiContext)return;try{conststatus=kioskManager.getKioskStatus();// 已为本应用锁定,无需重复进入if(status.isKioskMode&&status.kioskBundleName===this.uiContext.bundleName){hilog.info(DOMAIN,TAG,"已处于Kiosk锁定模式");return;}// 进入单应用锁定awaitkioskManager.enterKioskMode(this.uiContext);hilog.info(DOMAIN,TAG,"成功进入商用Kiosk锁机模式");}catch(err){conste=errasBusinessError;// 错误码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退出锁机,支持密码校验、状态实时展示:

import{ComponentV2,Local}from'@kit.ArkUI';import{kioskManager,common}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{BusinessError}from'@kit.BasicServicesKit';constTAG="KioskPage";constADMIN_PWD="admin123456";// 管理员退出密码,生产环境加密存储@Entry@ComponentV2struct KioskIndex{@LocalkioskEnable:boolean=false;@LocalinputPwd:string="";@LocaltipText:string="商用自助终端 · 已锁定,仅管理员可退出";privateuiCtx:common.UIAbilityContext|null=null;aboutToAppear(){this.uiCtx=getContext(this)ascommon.UIAbilityContext;this.refreshKioskStatus();// 监听锁机状态变化kioskManager.on("kioskChange",()=>{this.refreshKioskStatus();});}aboutToDisappear(){kioskManager.off("kioskChange");}// 刷新当前锁机状态privaterefreshKioskStatus(){conststatus=kioskManager.getKioskStatus();this.kioskEnable=status.isKioskMode;if(this.kioskEnable){this.tipText=`锁定生效,当前应用:${status.kioskBundleName}`;}else{this.tipText="未进入Kiosk锁定模式";}}// 管理员退出锁机模式privateasyncexitLockMode(){if(this.inputPwd!==ADMIN_PWD){this.tipText="密码错误,无法退出锁定";return;}if(!this.uiCtx)return;try{awaitkioskManager.exitKioskMode(this.uiCtx);this.tipText="已成功退出Kiosk锁机模式";this.inputPwd="";}catch(err){conste=errasBusinessError;this.tipText=`退出失败:${e.message}`;hilog.error(0x0005,TAG,`退出Kiosk异常:${JSON.stringify(err)}`);}}build(){Column({space:30}){Text("商用自助终端 Kiosk 锁定演示").fontSize(24).fontWeight(FontWeight.Bold).margin({top:40});Text(this.tipText).fontSize(16).fontColor(this.kioskEnable?"#00B42A":"#F53F3F");// 业务自助交互区域(客户操作区)Column(){Text("客户业务操作区").fontSize(20)Button("业务办理").width(200).height(50).backgroundColor("#0A59F7")}.width("90%").height(220).padding(20).backgroundColor("#F5F7FA").borderRadius(12);// 管理员退出区域(隐藏给普通客户,运维使用)Column({space:12}){Text("管理员退出锁机(仅运维)").fontSize(14).fontColor("#666");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模式仍存在少量逃逸路径,商用终端需叠加四层防护:

5.1 防护1:开机自启

metadata:ohos.ability.startup:auto_start,设备上电自动拉起应用并进入锁机,无需人工点开。

5.2 防护2:窗口全屏+隐藏系统栏

Ability窗口阶段强制隐藏状态栏、导航栏,无任何系统UI可触发下拉手势。

5.3 防护3:限制应用被后台销毁后自动重启

配置launchType:singleTask,系统内存回收后自动重启Ability,重新进入Kiosk锁机。

5.4 防护4:设备MDM管控(高阶商用)

企业批量终端搭配HEM设备管理平台:

  1. 禁用USB调试、文件传输;
  2. 屏蔽设置、应用市场、浏览器;
  3. 限制物理按键(音量、电源长按);
  4. 远程下发指令进入/退出Kiosk,无需现场输入密码。

六、调试与打包完整流程

  1. AGC申请受控Profile:勾选ohos.permission.ENTERPRISE_SET_KIOSK,提交商用自助终端场景材料,等待审核(1~3工作日);
  2. 配置企业正式签名:DevEco Studio导入下载的p12证书、p7b Profile;
  3. 真机调试:仅企业商用设备支持,普通消费手机调用API会报权限不足;模拟器无Kiosk系统服务,无法调试;
  4. 打包Release商用包:Build → Build Hap(s),使用带权限的签名;
  5. 设备安装验证:安装后启动自动进入锁机,测试下拉通知、返回手势、Home键全部失效。

七、高频踩坑避坑大全

坑1:enterKioskMode 报错 权限不足

  1. 未使用企业认证账号;
  2. AGC申请Profile时未勾选ENTERPRISE_SET_KIOSK
  3. 使用DevEco自动调试签名,无受控权限;
  4. module.json5未声明对应权限。

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

一台设备同一时间仅允许一个应用锁定,需先退出原有应用的Kiosk模式,再执行当前应用进入锁机。

坑3:切换分屏/下拉通知栏仍能调出系统UI

  • 未在WindowStage设置全屏+透明系统栏;
  • 窗口配置未开启autoHiddenNavigationBar/autoHiddenStatusBar
  • 设备非企业商用固件,消费版系统管控能力受限。

坑4:应用后台被杀后,锁机失效

解决方案:

  1. 配置开机自启;
  2. singleTask单实例启动模式;
  3. onForeground自动执行autoEnterKiosk,切前台重新上锁。

坑5:普通个人手机无法使用Kiosk API

底层限制:ENTERPRISE_SET_KIOSK仅对企业商用设备、企业MDM应用开放,个人消费手机无系统授权通道。

坑6:退出锁机后系统UI异常(导航栏不恢复)

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

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

  1. 密码安全:管理员退出密码禁止硬编码,使用SecureStorage加密存储,支持后台远程修改;
  2. 日志审计:Kiosk进入/退出、密码验证全部写入系统日志,可追溯运维操作;
  3. 异常兜底:onForeground自动重新上锁,防止进程异常解锁;
  4. 分层UI隔离:客户操作区与管理员退出面板视觉隔离,现场隐藏密码输入区域;
  5. 批量运维:多终端接入HEM MDM平台,远程一键切换锁机状态,无需现场操作;
  6. 断电保护:开启开机自启,断电重启自动恢复锁定,无人值守稳定运行。

总结

鸿蒙7 Kiosk商用锁定是面向线下自助终端的企业级管控方案,核心依赖kioskManager套件+企业受控权限,实现单应用完全锁定、屏蔽所有系统逃逸入口。
完整落地分为资质申请→工程配置→Ability自动上锁→管理员密码退出→多层加固五步,普通个人应用无法使用,仅企业商用自助设备适配。开发重点做好权限申请、前台自动重锁、窗口全屏隐藏系统栏三层核心逻辑,即可满足门店、政务、零售终端无人值守商用场景。