android 增加一个新的硬按键

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

添加新按键,则在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());
}












  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android的Toast是一个简单的消息弹出窗口,通常用于向用户显示短暂的消息。但是,Toast默认情况下不支持添加按钮。如果您想在Toast中添加一个按钮,您可以考虑使用自定义布局和自定义Toast。 以下是一些示例代码,可以帮助您创建一个带有按键的自定义Toast: 1. 首先,创建一个自定义的布局文件,包含一个TextView和一个Button。 ```xml <!-- custom_toast.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#AA000000" android:orientation="horizontal" android:padding="8dp"> <TextView android:id="@+id/text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textColor="#FFFFFF" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OK" /> </LinearLayout> ``` 2. 在您的Activity中,使用LayoutInflater加载自定义布局文件,并使用Toast显示它。您还可以在按钮上设置一个OnClickListener来处理点击事件。 ```java // 定义Toast的显示时间 private static final int TOAST_DURATION = Toast.LENGTH_SHORT; // 显示一个带有按键的Toast public void showCustomToast() { // 加载自定义布局文件 LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.custom_toast, null); // 获取布局中的TextView和Button TextView text = (TextView) layout.findViewById(R.id.text); Button button = (Button) layout.findViewById(R.id.button); // 设置TextView的文本内容 text.setText("这是一个带有按键的Toast"); // 创建一个的Toast对象 Toast toast = new Toast(getApplicationContext()); toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0); toast.setDuration(TOAST_DURATION); toast.setView(layout); // 设置Button的OnClickListener button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 处理按钮的点击事件 Toast.makeText(getApplicationContext(), "按钮已点击", Toast.LENGTH_SHORT).show(); } }); // 显示Toast toast.show(); } ``` 这样,您就可以创建一个带有按键的自定义Toast了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值