当前位置: 首页 > news >正文

OpenHarmony定制系统组合按键(二)

一、开发环境

系统版本:OpenHarmony 4.0.10.13
设备平台:rk3568
SDK版本:fullSDK 4.0.10.13
DevEco Studio版本:4.1.0.400

二、需求背景

定制OpenHarmony 系统组合按键功能,例如仿Android Power + VOL_Up组合键实现截屏功能

为了实现需求,上一文OpenHarmony定制系统组合按键(一)中创建了一个开机自启的后台服务,将用来订阅组合按键事件,本文详细介绍如何订阅系统组合事件

三、ServiceExtensionAbility订阅组合按键

3.1 定义组合按键配置

首先在ServiceExtAbility.ets中定义好组合按键的配置
这里定义了两组:

  • Power + volUp > 截屏
  • Mute + volDown >系统设置
const SCREENSHOT_KEY_OPTIONS: inputConsumer.KeyOptions = {preKeys: [KeyCode.KEYCODE_POWER],finalKey: KeyCode.KEYCODE_VOLUME_UP,isFinalKeyDown: true,finalKeyDownDuration: 0
}const SETTINGS_KEY_OPTIONS: inputConsumer.KeyOptions = {preKeys: [KeyCode.KEYCODE_MUTE],finalKey: KeyCode.KEYCODE_VOLUME_DOWN,isFinalKeyDown: true,finalKeyDownDuration: 0
}

3.2 订阅组合按键

在ServiceExtAbility.ets的onCreate()中

export default class ServiceExtAbility extends ServiceExtensionAbility {onCreate(want: Want): void {let serviceExtensionContext = this.context;hilog.info(DOMAIN_NUMBER, TAG, `onCreate, want: ${want.abilityName}`);//订阅截屏组合按键this.registerScreenshotKeys();//订阅打开设置组合按键this.registerSettingsKeys();};//订阅截屏组合按键registerScreenshotKeys() {console.info(TAG, "registerScreenshotKeys is called")//订阅截屏组合按键let screenshotCallback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `screenshotKeyOptions: ${JSON.stringify(keyOptions)}`);//跳转截屏应用this.context.startAbility({bundleName: 'com.ohos.screenshot',abilityName: 'com.ohos.screenshot.ServiceExtAbility',parameters: undefined}).then(() => {console.info(TAG, 'startAbility, then');}).catch((error: BusinessError) => {console.error(TAG, `startAbility, error: ${JSON.stringify(error)}`);});}try {inputConsumer.on("key", SCREENSHOT_KEY_OPTIONS, screenshotCallback);} catch (error) {console.error(TAG, `Subscribe screenshot failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}//订阅打开设置组合按键registerSettingsKeys() {console.info(TAG, "registerSettingsKeys is called")//订阅截屏组合按键let openSettingsCallback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `registerSettingsKeys: ${JSON.stringify(keyOptions)}`);//跳转系统设置this.context.startAbility({bundleName: 'com.ohos.settings',abilityName: 'com.ohos.settings.MainAbility',parameters: undefined}).then(() => {console.info(TAG, 'startAbility, then');}).catch((error: BusinessError) => {console.error(TAG, `startAbility, error: ${JSON.stringify(error)}`);});}try {inputConsumer.on("key", SETTINGS_KEY_OPTIONS, openSettingsCallback);} catch (error) {console.error(TAG, `Subscribe open Settings failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}}

3.3

当service 关闭时也需取消订阅

export default class ServiceExtAbility extends ServiceExtensionAbility {...//取消订阅截屏组合按键unregisterScreenshotKeys() {console.info(TAG, "unregisterScreenshotKeys is called");let callback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `keyOptions: ${JSON.stringify(keyOptions)}`);}try {inputConsumer.off("key", SCREENSHOT_KEY_OPTIONS, callback);console.info(`Unsubscribe screenshot keys success`);} catch (error) {console.error(`Execute failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}//取消订阅打开设置组合按键unregisterSettingsKeys() {console.info(TAG, "unregisterSettingsKeys is called");let callback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `keyOptions: ${JSON.stringify(keyOptions)}`);}try {inputConsumer.off("key", SETTINGS_KEY_OPTIONS, callback);console.info(`Unsubscribe open Settings keys success`);} catch (error) {console.error(`Execute failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}...onDestroy(): void {this.unregisterScreenshotKeys()this.unregisterSettingsKeys()hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy');};
}

效果

Power + volUp > 截屏
请添加图片描述

Power + volDown > 跳转系统设置
请添加图片描述

总结

通过本文已基本实现组合键截屏和跳转设置功能,不过细心的同学肯定也发现了,在响应组合键的同时也响应了单独的音量键,这体验并不好,后文将通过另外一种方式实现需求,并改善这一问题

源码

module.json5

{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "ServiceExtAbility","deviceTypes": ["default","tablet"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ets","description": "$string:EntryAbility_desc","icon": "$media:icon","label": "$string:EntryAbility_label","startWindowIcon": "$media:startIcon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]}],"extensionAbilities": [{"name": "ServiceExtAbility","icon": "$media:icon","label": "$string:EntryAbility_label","description": "service","type": "service","exported": true,"srcEntry": "./ets/services/ServiceExtAbility.ets"}],"requestPermissions": [{"name": "ohos.permission.START_ABILITIES_FROM_BACKGROUND"},{"name": "ohos.permission.CAPTURE_SCREEN"}]}
}

ServiceExtAbility.ets源码

import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
import Want from '@ohos.app.ability.Want';
import hilog from '@ohos.hilog';
import rpc from '@ohos.rpc';
import inputConsumer from '@ohos.multimodalInput.inputConsumer';
import { KeyCode } from '@ohos.multimodalInput.keyCode';
import { BusinessError } from '@ohos.base';const TAG: string = '[ServiceExtAbility]';
const DOMAIN_NUMBER: number = 0xFF00;const SCREENSHOT_KEY_OPTIONS: inputConsumer.KeyOptions = {preKeys: [KeyCode.KEYCODE_POWER],finalKey: KeyCode.KEYCODE_VOLUME_UP,isFinalKeyDown: true,finalKeyDownDuration: 0
}const SETTINGS_KEY_OPTIONS: inputConsumer.KeyOptions = {preKeys: [KeyCode.KEYCODE_POWER],finalKey: KeyCode.KEYCODE_VOLUME_DOWN,isFinalKeyDown: true,finalKeyDownDuration: 0
}class ServiceStub extends rpc.RemoteObject {constructor(des: string) {super(des);}
}export default class ServiceExtAbility extends ServiceExtensionAbility {onCreate(want: Want): void {let serviceExtensionContext = this.context;hilog.info(DOMAIN_NUMBER, TAG, `onCreate, want: ${want.abilityName}`);//订阅截屏组合按键this.registerScreenshotKeys();//订阅打开设置组合按键this.registerSettingsKeys();};registerScreenshotKeys() {console.info(TAG, "registerScreenshotKeys is called")//订阅截屏组合按键let screenshotCallback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `screenshotKeyOptions: ${JSON.stringify(keyOptions)}`);this.context.startAbility({bundleName: 'com.ohos.screenshot',abilityName: 'com.ohos.screenshot.ServiceExtAbility',parameters: undefined}).then(() => {console.info(TAG, 'startAbility, then');}).catch((error: BusinessError) => {console.error(TAG, `startAbility, error: ${JSON.stringify(error)}`);});}try {inputConsumer.on("key", SCREENSHOT_KEY_OPTIONS, screenshotCallback);} catch (error) {console.error(TAG, `Subscribe screenshot failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}unregisterScreenshotKeys() {console.info(TAG, "unregisterScreenshotKeys is called");let callback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `keyOptions: ${JSON.stringify(keyOptions)}`);}try {inputConsumer.off("key", SCREENSHOT_KEY_OPTIONS, callback);console.info(`Unsubscribe screenshot keys success`);} catch (error) {console.error(`Execute failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}registerSettingsKeys() {console.info(TAG, "registerSettingsKeys is called")//订阅截屏组合按键let openSettingsCallback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `registerSettingsKeys: ${JSON.stringify(keyOptions)}`);this.context.startAbility({bundleName: 'com.ohos.settings',abilityName: 'com.ohos.settings.MainAbility',parameters: undefined}).then(() => {console.info(TAG, 'startAbility, then');}).catch((error: BusinessError) => {console.error(TAG, `startAbility, error: ${JSON.stringify(error)}`);});}try {inputConsumer.on("key", SETTINGS_KEY_OPTIONS, openSettingsCallback);} catch (error) {console.error(TAG, `Subscribe open Settings failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}unregisterSettingsKeys() {console.info(TAG, "unregisterSettingsKeys is called");let callback = (keyOptions: inputConsumer.KeyOptions) => {console.info(TAG, `keyOptions: ${JSON.stringify(keyOptions)}`);}try {inputConsumer.off("key", SETTINGS_KEY_OPTIONS, callback);console.info(`Unsubscribe open Settings keys success`);} catch (error) {console.error(`Execute failed, error: ${JSON.stringify(error, [`code`, `message`])}`);}}onRequest(want: Want, startId: number): void {hilog.info(DOMAIN_NUMBER, TAG, `onRequest, want: ${want.abilityName}`);};onConnect(want: Want): rpc.RemoteObject {hilog.info(DOMAIN_NUMBER, TAG, `onConnect, want: ${want.abilityName}`);// 返回ServiceExtImpl对象,客户端获取后便可以与ServiceExtensionAbility进行通信return new ServiceStub('ServiceExtAbilityService');};onDisconnect(want: Want): void {hilog.info(DOMAIN_NUMBER, TAG, `onDisconnect, want: ${want.abilityName}`);};onDestroy(): void {this.unregisterScreenshotKeys()this.unregisterSettingsKeys()hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy');};
};

相关文章:

  • Linux线程入门
  • 麻省理工新突破:家庭场景下机器人实现精准控制,real-to-sim-to-real学习助力
  • Linux上给SD卡创建分区
  • Linux下挂载目录如何进行操作
  • 华为OD机试真题——最小矩阵宽度(宽度最小的子矩阵)(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
  • 【异常解决】一招解决Navicat连接线上数据库时,隔一段时间不操作出现的卡顿问题
  • 【JavaEE】Spring事务
  • 【JavaEE】-- 网络原理
  • 深度解析 torch.mean 的替代方案
  • Java消息队列应用:Kafka、RabbitMQ选择与优化
  • PyTorch 入门学习笔记
  • 记录一次session安装应用recyclerview更新数据的bug
  • Qt 的简单示例 -- 地址簿
  • 聊聊JVM怎么调优?(实战总结)
  • 单链表反序实现
  • 数据结构 - 树的遍历
  • 从零开始搞个简易分布式部署环境
  • 【大模型原理与技术-毛玉仁】第二章 大语言模型架构
  • LangChain快速入门:使用LangChain构建高效的并行语言处理链
  • 切换到旧提交,同时保证当前修改不丢失
  • 游戏网站免费入口/长沙专业做网站公司
  • 做营销型网站公司/站长之家工具
  • 周口建设局网站/怎么从网上找国外客户
  • 三网合一网站建设公司/竞价推广账户竞价托管收费
  • 餐饮网站建设教程/营销型网站建设专家
  • 做网站域名费一般多少钱/抖音代运营公司