KeyCode及KeyCode分发机制

文章目录

  • 需求场景
    • 纯KeyCode 快捷操作
    • KeyCode 按键响应操作、拦截
  • 一、工作中常用KeyCode
  • 二、KeyCode大全
  • 三、KeyCode 响应事件
    • 事件输入流程
    • 事件响应
      • 源码分析
      • 源码举例说明


需求场景

纯KeyCode 快捷操作

  • 经常在代码中实现返回、Home 、音量加减、截屏 等功能实现,代码中硬编码 shell 脚本 模拟 KeyCode事件
  • 物理按键调试,模拟物理按键测试用:按键功能,物理按键驱动层已经调试完成,但有没有完整的硬件方便调试,应用层模拟物理按键功能来调试。比如:Android方案中,电视产品、音箱产品、带屏的Android各种方案
    都是有物理按键的,如果自己测试验证物理按键的功能呢,那就需要自己来模拟KeyEventCode 来模拟按键,先自测。
  • 遥控器功能【投影产品】:一般根据蓝牙方案、红外方案实现遥控功能,传递给系统的都是Key的键值,系统自带标准的键值,这样就形成一套标准的流程了,系统根据键值做出反馈或者系统收到对应的键值反馈给上层,上层来处理业务逻辑。
  • 游戏类产品,手柄的控制。手柄上面的功能按钮其实就是一些物理按键,点击物理按键,系统或者应用监听后给出反馈。那么在实际测试的时候,就需要模拟按键来测试验证
  • 如果Android平板作为电脑使用,插上USB,那么Android平板作为电脑来时候,就必须响应键盘上面的所有按键,这些物理按键也是通过KeyCode
    来传递给系统,准确来说是系统来响应这些KeyCode,进而再处理响应的逻辑。

总的来讲:系统响应KeyCode,这些KeyCode是外设作为输入源,KeyCode 键值就是Android一套标准的协议

KeyCode 按键响应操作、拦截

比如物理按键操作之后,系统是如何分发、响应、处理、拦截呢? 比如我们需要客制化一些物理按键功能,如何实现呢?


一、工作中常用KeyCode

枚举值键值功能说明
KEYCODE_HOME3主屏幕键
KEYCODE_BACK4返回键
KEYCODE_DPAD_UP19向上方向键
KEYCODE_DPAD_DOWN20向下方向键
KEYCODE_DPAD_LEFT21向左方向键
KEYCODE_DPAD_RIGHT22向右方向键
KEYCODE_DPAD_CENTER23中心键
KEYCODE_VOLUME_UP24手机音量+
KEYCODE_VOLUME_DOWN25手机音量-
KEYCODE_POWER26电源键
KEYCODE_EXPLORER64启动浏览器程序
KEYCODE_MEDIA_PLAY_PAUSE85多媒体播放、暂停键
KEYCODE_MEDIA_STOP86停止键
KEYCODE_MEDIA_NEXT87下一首键
KEYCODE_MEDIA_PREVIOUS88上一首键
KEYCODE_MEDIA_REWIND89快退键
KEYCODE_MEDIA_FAST_FORWARD90快进键
KEYCODE_MEDIA_PLAY126播放键
KEYCODE_MEDIA_PAUSE127暂停键
KEYCODE_VOLUME_MUTE164手机扬声器静音
KEYCODE_APP_SWITCH187任务管理 最近历史任务
KEYCODE_MUSIC209启动音乐
KEYCODE_BRIGHTNESS_DOWN220亮度减少
KEYCODE_BRIGHTNESS_UP221亮度增加
KEYCODE_DPAD_DOWN_LEFT269向左下方向键
KEYCODE_DPAD_DOWN_RIGHT271向右下方向键
KEYCODE_DPAD_UP_LEFT268向左上方向键
KEYCODE_DPAD_UP_RIGHT270向右上方向键

备注:如何用命令来模拟执行按键操作
枚举方式:adb shell input keyevent KEYCODE_HOME

code方式:adb shell input keyevent 3

二、KeyCode大全

这里给出谷歌官方KeyEvent 事件,里面总结了所有的KeyCode
官方KeyCode


三、KeyCode 响应事件

事件输入流程

从大的方向将,物理按键始于外部输入,在Kernel 响应,再传递到Service或者View层消费,对于Kernel层、系统层暂不研究。
输入设备键值从底层到应用层的映射流程
在这里插入图片描述

事件响应

源码分析

源码位置:
PhoneWindowManager
这里涉及到 源码中的PhoneWindowManager 来响应物理按键事件并进行分发:

// You can only start consuming the key gesture if ACTION_DOWN and repeat count// is 0. If you start intercepting the key halfway, then key will not be consumed// and will be sent to apps for processing too.// e.g. If a certain combination is only handled on ACTION_UP (i.e.// interceptShortcut() returns true only for ACTION_UP), then since we already// sent the ACTION_DOWN events to the application, we MUST also send the// ACTION_UP to the application.// So, to ensure that your intercept logic works properly, and we don't send any// conflicting events to application, make sure to consume the event on// ACTION_DOWN even if you want to do something on ACTION_UP. This is essential// to maintain event parity and to not have incomplete key gestures.@SuppressLint("MissingPermission")private boolean interceptSystemKeysAndShortcuts(IBinder focusedToken, KeyEvent event) {final boolean keyguardOn = keyguardOn();final int keyCode = event.getKeyCode();final int repeatCount = event.getRepeatCount();final int metaState = event.getMetaState();final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;final boolean canceled = event.isCanceled();final int displayId = event.getDisplayId();final int deviceId = event.getDeviceId();final boolean firstDown = down && repeatCount == 0;// Cancel any pending meta actions if we see any other keys being pressed between the// down of the meta key and its corresponding up.if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {mPendingMetaAction = false;}// Any key that is not Alt or Meta cancels Caps Lock combo tracking.if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {mPendingCapsLockToggle = false;}if (isUserSetupComplete() && !keyguardOn) {if (mModifierShortcutManager.interceptKey(event)) {dismissKeyboardShortcutsMenu();mPendingMetaAction = false;mPendingCapsLockToggle = false;return true;}}switch (keyCode) {case KeyEvent.KEYCODE_HOME:return handleHomeShortcuts(focusedToken, event);case KeyEvent.KEYCODE_MENU:// Hijack modified menu keys for debugging featuresfinal int chordBug = KeyEvent.META_SHIFT_ON;if (mEnableShiftMenuBugReports && firstDown&& (metaState & chordBug) == chordBug) {Intent intent = new Intent(Intent.ACTION_BUG_REPORT);mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,null, null, null, 0, null, null);logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);return true;}break;case KeyEvent.KEYCODE_RECENT_APPS:if (firstDown) {showRecentApps(false /* triggeredFromAltTab */);logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);}return true;case KeyEvent.KEYCODE_APP_SWITCH:if (!keyguardOn) {if (firstDown) {preloadRecentApps();} else if (!down) {toggleRecentApps();logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);}}return true;case KeyEvent.KEYCODE_A:if (firstDown && event.isMetaPressed()) {launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,deviceId, event.getEventTime(),AssistUtils.INVOCATION_TYPE_UNKNOWN);logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);return true;}break;case KeyEvent.KEYCODE_H:case KeyEvent.KEYCODE_ENTER:if (event.isMetaPressed()) {return handleHomeShortcuts(focusedToken, event);}break;case KeyEvent.KEYCODE_I:if (firstDown && event.isMetaPressed()) {showSystemSettings();logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);return true;}break;case KeyEvent.KEYCODE_L:if (firstDown && event.isMetaPressed()) {lockNow(null /* options */);logKeyboardSystemsEvent(event, KeyboardLogEvent.LOCK_SCREEN);return true;}break;case KeyEvent.KEYCODE_N:if (firstDown && event.isMetaPressed()) {if (event.isCtrlPressed()) {sendSystemKeyToStatusBarAsync(event);logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_NOTES);} else {toggleNotificationPanel();logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);}return true;}break;case KeyEvent.KEYCODE_S:if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);logKeyboardSystemsEvent(event, KeyboardLogEvent.TAKE_SCREENSHOT);return true;}break;case KeyEvent.KEYCODE_DEL:case KeyEvent.KEYCODE_ESCAPE:if (firstDown && event.isMetaPressed()) {logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);injectBackGesture(event.getDownTime());return true;}case KeyEvent.KEYCODE_DPAD_UP:if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {StatusBarManagerInternal statusbar = getStatusBarManagerInternal();if (statusbar != null) {statusbar.moveFocusedTaskToFullscreen(getTargetDisplayIdForKeyEvent(event));logKeyboardSystemsEvent(event, KeyboardLogEvent.MULTI_WINDOW_NAVIGATION);return true;}}break;case KeyEvent.KEYCODE_DPAD_DOWN:if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {StatusBarManagerInternal statusbar = getStatusBarManagerInternal();if (statusbar != null) {statusbar.enterDesktop(getTargetDisplayIdForKeyEvent(event));logKeyboardSystemsEvent(event, KeyboardLogEvent.DESKTOP_MODE);return true;}}break;case KeyEvent.KEYCODE_DPAD_LEFT:if (firstDown && event.isMetaPressed()) {if (event.isCtrlPressed()) {enterStageSplitFromRunningApp(true /* leftOrTop */);logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);} else {logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);injectBackGesture(event.getDownTime());}return true;}break;case KeyEvent.KEYCODE_DPAD_RIGHT:if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {enterStageSplitFromRunningApp(false /* leftOrTop */);logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);return true;}break;case KeyEvent.KEYCODE_SLASH:if (firstDown && event.isMetaPressed() && !keyguardOn) {toggleKeyboardShortcutsMenu(event.getDeviceId());logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_SHORTCUT_HELPER);return true;}break;case KeyEvent.KEYCODE_ASSIST:Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");return true;case KeyEvent.KEYCODE_VOICE_ASSIST:Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"+ " interceptKeyBeforeQueueing");return true;case KeyEvent.KEYCODE_VIDEO_APP_1:case KeyEvent.KEYCODE_VIDEO_APP_2:case KeyEvent.KEYCODE_VIDEO_APP_3:case KeyEvent.KEYCODE_VIDEO_APP_4:case KeyEvent.KEYCODE_VIDEO_APP_5:case KeyEvent.KEYCODE_VIDEO_APP_6:case KeyEvent.KEYCODE_VIDEO_APP_7:case KeyEvent.KEYCODE_VIDEO_APP_8:case KeyEvent.KEYCODE_FEATURED_APP_1:case KeyEvent.KEYCODE_FEATURED_APP_2:case KeyEvent.KEYCODE_FEATURED_APP_3:case KeyEvent.KEYCODE_FEATURED_APP_4:case KeyEvent.KEYCODE_DEMO_APP_1:case KeyEvent.KEYCODE_DEMO_APP_2:case KeyEvent.KEYCODE_DEMO_APP_3:case KeyEvent.KEYCODE_DEMO_APP_4:Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");return true;case KeyEvent.KEYCODE_BRIGHTNESS_UP:case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:if (down) {int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;// Disable autobrightness if it's onint auto = Settings.System.getIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS_MODE,Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,UserHandle.USER_CURRENT_OR_SELF);if (auto != 0) {Settings.System.putIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS_MODE,Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,UserHandle.USER_CURRENT_OR_SELF);}int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;float minLinearBrightness = mPowerManager.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);float maxLinearBrightness = mPowerManager.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);float adjustedGammaBrightness =gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;adjustedGammaBrightness = MathUtils.constrain(adjustedGammaBrightness, 0f,1f);float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(adjustedGammaBrightness);adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness,minLinearBrightness, maxLinearBrightness);mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION| Intent.FLAG_ACTIVITY_NO_USER_ACTION);intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));}return true;case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:if (down) {mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_DOWN);}return true;case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:if (down) {mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_UP);}return true;case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:// TODO: Add logicif (!down) {logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_TOGGLE);}return true;case KeyEvent.KEYCODE_VOLUME_UP:case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_MUTE:if (mUseTvRouting || mHandleVolumeKeysInWM) {// On TVs or when the configuration is enabled, volume keys never// go to the foreground app.dispatchDirectAudioEvent(event);return true;}// If the device is in VR mode and keys are "internal" (e.g. on the side of the// device), then drop the volume keys and don't forward it to the// application/dispatch the audio event.if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {final InputDevice d = event.getDevice();if (d != null && !d.isExternal()) {return true;}}break;case KeyEvent.KEYCODE_TAB:if (firstDown && !keyguardOn && isUserSetupComplete()) {if (event.isMetaPressed()) {showRecentApps(false);logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);return true;} else if (mRecentAppsHeldModifiers == 0) {final int shiftlessModifiers =event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {mRecentAppsHeldModifiers = shiftlessModifiers;showRecentApps(true);logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);return true;}}}break;case KeyEvent.KEYCODE_ALL_APPS:if (!down) {mHandler.removeMessages(MSG_HANDLE_ALL_APPS);Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);msg.setAsynchronous(true);msg.sendToTarget();logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);}return true;case KeyEvent.KEYCODE_NOTIFICATION:if (!down) {toggleNotificationPanel();logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);}return true;case KeyEvent.KEYCODE_SEARCH:if (firstDown && !keyguardOn) {switch (mSearchKeyBehavior) {case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {launchTargetSearchActivity();logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SEARCH);return true;}case SEARCH_BEHAVIOR_DEFAULT_SEARCH:default:break;}}break;case KeyEvent.KEYCODE_LANGUAGE_SWITCH:if (firstDown) {int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;sendSwitchKeyboardLayout(event, focusedToken, direction);logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH);return true;}break;case KeyEvent.KEYCODE_META_LEFT:case KeyEvent.KEYCODE_META_RIGHT:if (down) {if (event.isAltPressed()) {mPendingCapsLockToggle = true;mPendingMetaAction = false;} else {mPendingCapsLockToggle = false;mPendingMetaAction = true;}} else {// Toggle Caps Lock on META-ALT.if (mPendingCapsLockToggle) {mInputManagerInternal.toggleCapsLock(event.getDeviceId());mPendingCapsLockToggle = false;logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);} else if (mPendingMetaAction) {if (!canceled) {launchAllAppsViaA11y();logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);}mPendingMetaAction = false;}}return true;case KeyEvent.KEYCODE_ALT_LEFT:case KeyEvent.KEYCODE_ALT_RIGHT:if (down) {if (event.isMetaPressed()) {mPendingCapsLockToggle = true;mPendingMetaAction = false;} else {mPendingCapsLockToggle = false;}} else {// hide recent if triggered by ALT-TAB.if (mRecentAppsHeldModifiers != 0&& (metaState & mRecentAppsHeldModifiers) == 0) {mRecentAppsHeldModifiers = 0;hideRecentApps(true, false);return true;}// Toggle Caps Lock on META-ALT.if (mPendingCapsLockToggle) {mInputManagerInternal.toggleCapsLock(event.getDeviceId());mPendingCapsLockToggle = false;logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);return true;}}break;case KeyEvent.KEYCODE_CAPS_LOCK:if (!down) {logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);}break;case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL:Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in"+ " interceptKeyBeforeQueueing");return true;case KeyEvent.KEYCODE_SETTINGS:if (mShortPressOnSettingsBehavior == SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL) {if (!down) {toggleNotificationPanel();logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);}return true;}break;case KeyEvent.KEYCODE_STEM_PRIMARY:if (prepareToSendSystemKeyToApplication(focusedToken, event)) {// Send to app.return false;} else {// Intercepted.sendSystemKeyToStatusBarAsync(event);return true;}case KeyEvent.KEYCODE_SCREENSHOT:if (emojiAndScreenshotKeycodesAvailable() && down && repeatCount == 0) {interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);}return true;}if (isValidGlobalKey(keyCode)&& mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {return true;}// Reserve all the META modifier combos for system behaviorreturn (metaState & KeyEvent.META_META_ON) != 0;}

源码举例说明

控制中,如下:

   case KeyEvent.KEYCODE_BRIGHTNESS_UP:case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:if (down) {int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;// Disable autobrightness if it's onint auto = Settings.System.getIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS_MODE,Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,UserHandle.USER_CURRENT_OR_SELF);if (auto != 0) {Settings.System.putIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS_MODE,Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,UserHandle.USER_CURRENT_OR_SELF);}int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;float minLinearBrightness = mPowerManager.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);float maxLinearBrightness = mPowerManager.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);float adjustedGammaBrightness =gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;adjustedGammaBrightness = MathUtils.constrain(adjustedGammaBrightness, 0f,1f);float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(adjustedGammaBrightness);adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness,minLinearBrightness, maxLinearBrightness);mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION| Intent.FLAG_ACTIVITY_NO_USER_ACTION);intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));}return true;

这里消费亮度

业务逻辑如下:

  • 获取当前亮度模式
  • 获取当前亮度、最大亮度、最小亮度
  • 调节亮度【用到了亮度曲线 从伽马曲线】
  • 发送亮度控制的Intent
    的接受者【实际为BrightnessDialog】

声音音量也是一样的,在这个方法中进行了处理一次,再响应给View来处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/143957.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot(40) — SpringBoot整合MyBatis-plus

前言 在上节中我们对MyBatis-plus特性有了一个整体的认识&#xff0c;然后也大致讲了些MyBatis与MyBatis-plus的不同之处。大家感兴趣的话&#xff0c;可参考以下文章 SpringBoot(39) — MyBatis-plus简介 这节我们来讲讲SpringBoot项目如何快速接入MyBatis-plus框架。 今天涉及…

开源网安多城联动、多形式开展网安周公益活动,传播网络安全知识

9月9日至15日&#xff0c;以“网络安全为人民&#xff0c;网络安全靠人民”为主题的2024年国家网络安全宣传周将在全国范围内统一开展&#xff0c;通过多样的形式、丰富的内容&#xff0c;助力全社会网络安全意识和防护技能提升。开源网安今年继续为各地企业、群众带来了丰富的…

BOE(京东方)领先科技赋能体育产业全面向新 以击剑、电竞、健身三大应用场景诠释未来健康运动新生活

巴黎全球体育盛会虽已闭幕&#xff0c;但世界范围内的运动热潮并未消退。9月12日&#xff0c;在北京恒通国际商务园&#xff08;UBP&#xff09;的之所ICC&#xff0c;BOE&#xff08;京东方&#xff09;开启了以“屏实力 FUN肆热爱”为主题的“科技赋能体育”互动体验活动。活…

esp32 wifi 联网后,用http 发送hello 用pc 浏览器查看网页

参考chatgpt Esp32可以配置为http服务器&#xff0c;可以socket编程。为了免除编写针对各种操作系统的app。完全可以用浏览器仿问esp32服务器&#xff0c;获取esp32的各种数据&#xff0c;甚至esp的音频&#xff0c;视频。也可以利用浏览器对esp进行各种操作。但esp不能主动仿…

vue3前端开发-小兔鲜超市-本地购物车列表页面的统计计算

vue3前端开发-小兔鲜超市-本地购物车列表页面的统计计算&#xff01;这一次&#xff0c;实现了一些本地购物车列表页面的&#xff0c;简单的计算。 代码如下所示&#xff1a; import { computed, ref } from vue import { defineStore } from pinia export const useCartStor…

web基础—dvwa靶场(八)SQL Injection(Blind)

SQL Injection(Blind)&#xff08;SQL注入之盲注&#xff09; SQL Injection(Blind)&#xff0c;SQL盲注&#xff0c;相比于常规的SQL注入&#xff0c;他不会将返回具体的数据信息或语法信息&#xff0c;只会将服务器包装后的信息返回到页面中。 常规SQL注入与SQL盲注详细对比…

css 样式简单学习(一)

目录 1. css 介绍 1.1 css 样式 1.2 css代码风格 1.2.1 书写格式 1.2.2 样式大小写​编辑 1.2.3 空格规范 2. 基础选择器 2.1 选择器的作用​编辑 2.2 选择器的分类 2.3 基础选择器 2.3.1 标签选择器​编辑 2.3.2 类选择器​编辑 2.3.3 类选择器-多类名​编辑 2.…

Unity 百度AI实现无绿幕拍照抠像功能(详解版)

目录 一、前言 1.抠像效果 2.去哪找百度ai抠图 3.基础流程跳过 二、获取AccessToken 1.什么是Token 2.为什么要获取Token 3.如何获取token 4.解析json 5.完整代码 三、抠像 1.准备地址 2.建立链接&#xff0c;和基本配置 3.图片格式转换 4.开始上传 5.获取回复…

python本地进程通讯----共享内存变量

背景 最近在开发实践中&#xff0c;接触到了需要多进程开发的场景。众所周知&#xff0c;进程和线程最大的区别就在于&#xff1a;进程是资源分配的最小单位&#xff0c;线程是cpu调度的最小单位。对于多进程开发来说&#xff0c;每一个进程都占据一块独立的虚拟内存空间&#…

Mobile net V系列详解 理论+实战(2)

Mobilenet 系列 实践部分一、数据集介绍二、模型整体框架三、模型代码详解四、总结 实践部分 本章针对实践通过使用pytorch一个实例对这部分内容进行吸收分析。本章节采用的源代码在这里感兴趣的读者可以自行下载操作。 一、数据集介绍 可以看到数据集本身被存放在了三个文件…

django学习入门系列之第十点《A 案例: 员工管理系统10》

文章目录 12 管理员操作12.4 密码加密12.5 获取对象&#xff08;防止id错误--编辑界面等&#xff09;12.6 编辑管理员12.7 重置密码 往期回顾 12 管理员操作 12.4 密码加密 密码不应该以明文的方式直接存储到数据库&#xff0c;应该加密才放进去 定义一个md5的方法&#xff…

4 html5 web components原生组件详细教程

web components 前面我们已经介绍过&#xff0c;这一期我们就来讲一讲具体用法和这其中的关键只是点&#xff1a; 1 基本使用 如果我们想实现一个封装的原生组件&#xff0c;那就离不开使用js去封装&#xff0c;这里主要就是基于HTMLElement这个类&#xff0c;去创建创建一个…

OpenCV运动分析和目标跟踪(2)累积操作函数accumulateSquare()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将源图像的平方加到累积器图像中。 该函数将输入图像 src 或其选定区域提升到2的幂次方&#xff0c;然后加到累积器 dst 中&#xff1a; dst ( …

Android WebView H5 Hybrid 混和开发

对于故乡&#xff0c;我忽然有了新的理解&#xff1a;人的故乡&#xff0c;并不止于一块特定的土地&#xff0c;而是一种辽阔无比的心情&#xff0c;不受空间和时间的限制&#xff1b;这心情一经唤起&#xff0c;就是你已经回到了故乡。——《记忆与印象》 前言 移动互联网发展…

用Python画一个五星红旗

#codingutf-8 import turtle import mathdef draw_polygon(aTurtle, size50, n3): 绘制正多边形args:aTurtle: turtle对象实例size: int类型&#xff0c;正多边形的边长n: int类型&#xff0c;是几边形 for i in range(n):aTurtle.forward(size)aTurtle.left(360.0/n)de…

esp32-C2 对接火山引擎实现语音转文本(二)

目录 一、 语音转文本初始化 二、 WedStream 事件处理函数 一、 语音转文本初始化 Volcengine_vtt_handle_t Volcengine_Vtt_Init(Volcengine_vtt_config_t *config) {// 管道配置audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();Volcengine_vtt_t *vt…

【从计算机的发展角度理解编程语言】C、CPP、Java、Python,是偶然还是应时代的产物?

参考目录 前言什么是"computer"?计算机的大致发展历程计算机系统结构阶段(1946~1981)计算机网络和视窗阶段(1982~2007)复杂信息系统阶段(2008~today)人工智能阶段 越新的语言是越好的吗、越值得学习吗&#xff1f; 前言 最近读了 《Python语言程序设计基础》 这本书…

数据结构与算法学习day21-回溯法

一、组合 1.题目 . - 力扣&#xff08;LeetCode&#xff09; 2思路 把组合问题抽象成树形结构&#xff08;N叉树&#xff09; 每次从集合中选取元素&#xff0c;可选择的范围随着选择的进行而收缩&#xff0c;调整可选择的范围。 图中可以发现n相当于树的宽度&#xff0c…

[Linux]进程控制详解

1.创建进程 进程调用fork,当控制转移到内核中的fork代码后&#xff0c;内核做&#xff1a; ● 分配新的内存块和内核数据结构给子进程 ● 将父进程部分数据结构内容拷贝至子进程 ● 添加子进程到系统进程列表当中 ● fork返回&#xff0c;开始调度器调度 这个前面提到过&#…

c++基础入门三

文章目录 C基础入门(三)auto关键字auto简介使用细则一、可以和指针联合使用二、在一行定义多个变量 不能使用场景一、不能作为函数的参数二、不能用来声明数组 基于for的循环使用条件 指针空值nullptr C基础入门(三) 回顾上集&#xff0c;我们介绍了C的函数重载&#xff0c;引…