android 增加一个新的硬按键

本文详细介绍了在Android系统中成功添加新按键的全过程,包括添加键码到不同文件、驱动配置、解析映射以及事件处理等关键步骤。同时,提供了在添加新按键过程中可能出现的问题及解决方案,帮助开发者避免常见错误,确保新按键能够正常工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面为项目中实际运用成功案例

添加新按键,则在KeyEvent.java的注释中有其说明,如下:

    // NOTE: If you add a new keycode here you must also add it to:
    //  isSystem()
    //  native/include/android/keycodes.h
    //  frameworks/base/include/ui/KeycodeLabels.h
    //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
    //  frameworks/base/core/res/res/values/attrs.xml
    //  emulator?
    //  LAST_KEYCODE
    //  KEYCODE_SYMBOLIC_NAMES
    //
    //  Also Android currently does not reserve code ranges for vendor-
    //  specific key codes.  If you have new key codes to have, you
    //  MUST contribute a patch to the open source project to define
    //  those new codes.  This is intended to maintain a consistent
    //  set of key code definitions across all Android devices.

上面为主要的大纲主旨,下面实例增加一个硬按键

KeycodeLabels.h


 {"SHORTCUT_1", 140},

attrs.xml

 <enum name="KEYCODE_SHORTCUT_1" value="140" />

native/include/android/keycodes.h是否需要加入:


 AKEYCODE_SHORTCUT_1 = 140,


KeyEvent

 public static final int KEYCODE_SHORTCUT_1 = 140;

device目录下找到项目的.mk文件,找到.kl文件,原生态是qwerty.kl,但是因为定制可能有的会自我重新 搞个.kl文件,增加如下:

key  129 SHORTCUT_1        WAKE_DROPPED

说明: 这里的SHORTCUT_1就是我们定义的android键值的字符形式,129则是linux键值

在EventHub.cpp中加载并解析这个map:.kl,那么得到的是linux键值129为key的string,这个string就是SHORTCUT_1,有了KeycodeLabels.h这个KEYCODES数组,就可以获得它对应的android键值了。


KeyPolicyImpl实现

    public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
            int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) {


上面方法里面进行判断是否为SHORTCUT_1

if ((keyCode == KeyEvent.KEYCODE_SHORTCUT_1) && !down) {

            Log.i(TAG, "coming check down  shortcut");
            mHandler.removeCallbacks(mShortCutLongPress);
        }

其mShortCutLongPress主要进行广播通知

    Runnable mShortCutLongPress = new Runnable() {

        public void run() {
            Log.d(TAG, "long mShortCutPress click shortCut");
          
            mShortCutPressed = false; 
            Intent intent = new Intent(IntentHelper.ACTION_SHORTCUT);
      
            mContext.sendBroadcast(intent);
        }
    };

上面mShortCutLongPress里面涉及到一个变量mShortCutPressed = false;是全局的

上面的

interceptKeyBeforeDispatching
上面面里面紧接着实现下面两个逻辑:

if (mShortCutPressed) {
            Log.i(TAG ," shortcut shortclick");
            if (keyCode == KeyEvent.KEYCODE_DLS_SHORTCUT_1) {

                mShortCutPressed = false;

                if (!down) {
                    Log.i(TAG, "down is fals  shortcut");

                    Intent intent = new Intent(IntentHelper.ACTION_RADIO_SHORTCUT);
               
                    mContext.sendBroadcast(intent);
                }
            }
            return false;
        }


else if (keyCode == KeyEvent.KEYCODE_SHORTCUT_1) {
            if(DEBUG)
                Log.d(TAG,"PhoneWindowManager->KEYCODE_SHORTCUT_1!!");

            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
            if (attrs != null) {
                final int type = attrs.type;
                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
                    return false;
                        }
                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
                for (int i=0; i<typeCount; i++) {
                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
                        return true;
                    }
                }
            }

            if (down && repeatCount == 0) {
                if (!keyguardOn) {
                    Log.i(TAG, "coming in KeyEvent.KEYCODE_SHORTCUT");
                    setKeyCode(keyCode);
                    mHandler.postDelayed(mShortCutLongPress,
                        ViewConfiguration.getGlobalActionKeyTimeout());
                }
                mShortCutPressed = true;
            }

            return true;
        } else if ......




 对于按键事件的处理一般如下文件中

PhoneWindowManager.java

PhoneWindow.java



添加新的按键过程中可能出现的问题
 

  1.按键框架层中相关变量都添加后,keycode=0.
     <1>确保驱动上报键值的准确性。
     <1>确保确定设备的kl文件。根据 /system/usr/idc 中的idc 文件,以及 在EventHub.cpp中打印 设备的配置 文件,确定设备的kl 文件,设备不止一个kl文件
     <3> kl 文件的键值映射正确。
         key 123 KEYCODENAME,  KEYCODENAME 与驱动没有关系,必须保证这个 keycode 被添加成功。在KeyEvent.java 中的注释中已经说明了用户添加一个新的按键所需要修改的所有文件。
     <4> 框架层修改完成后,为了确保正确,将ap侧代码全部编译一遍,重新烧录system.img.在PhoneWindowManager 中验证按键是否正常。


有关:/frameworks/base/libs/ui/Input.cpp,我不理解什么是系统按键,比如我们车载上的远程按键能是系统按键吗?后来请教老王帮我解释了下:

有些耳机上有两个按键为音乐的上一首下一首的按键值,这些是android系统自带的,我们为了兼容第三方这些值都不能删,而可以往里面加没事

bool KeyEvent::isSystemKey(int32_t keyCode) {
    switch (keyCode) {
        case AKEYCODE_MENU:
        case AKEYCODE_SOFT_RIGHT:
        case AKEYCODE_HOME:
        case AKEYCODE_BACK:
        case AKEYCODE_CALL:
        case AKEYCODE_ENDCALL:
        case AKEYCODE_VOLUME_UP:
        case AKEYCODE_VOLUME_DOWN:
        case AKEYCODE_VOLUME_MUTE:
        case AKEYCODE_MUTE:
        case AKEYCODE_POWER:
        case AKEYCODE_HEADSETHOOK:
        case AKEYCODE_MEDIA_PLAY:
        case AKEYCODE_MEDIA_PAUSE:
        case AKEYCODE_MEDIA_PLAY_PAUSE:
        case AKEYCODE_MEDIA_STOP:
        case AKEYCODE_MEDIA_NEXT:
        case AKEYCODE_MEDIA_PREVIOUS:
        case AKEYCODE_MEDIA_REWIND:
        case AKEYCODE_MEDIA_RECORD:
        case AKEYCODE_MEDIA_FAST_FORWARD:
        case AKEYCODE_CAMERA:
        case AKEYCODE_FOCUS:
        case AKEYCODE_SEARCH:
            return true;
    }
   
    return false;
}

bool KeyEvent::isSystemKey() const {
    return isSystemKey(getKeyCode());
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值