项目要求:该项目由于没有使用android5.0,导致启动bluetooth的蓝牙audio slave功能必须使用第三方模组,该第三方模组,启动是通过android主板通过GPIO控制。UI界面是通过图形选择或者一个kpd组合按键来打开关闭或者是启动蓝牙搜索功能。
1,用户按键的侦测:
标准的行为,用户的组合按键,kernel里面向上层发送scancode,然后framework把scancode转换成keycode的keyevent,该keyevent会被PhoneWindows接受并处理。
对于mtk,从按键到keycode,已经被封装起来,这个封装的工具就是dct.
例如,我们的项目组合按键是:KCOL2+KROW1,我们可以在图形工具中如选择我们的配置
在例子中,我们设置该案件的keycode是SYM
当然,也可以自己定义新的keycode,我嫌麻烦,就直接使用现成的,如何定义新的按键,请看附录:
2,侦测用户按键行为,发送相应的intent
上面的keycode在发送到各个window之前,是被PhoneWindowManager.java接收到的,在其中有一个方法:
@Override
public intinterceptKeyBeforeQueueing(KeyEvent event, int policyFlags, booleanisScreenOn) {
望文生义,看名字我们就知道这个函数的作用。我们在代码中如下拦截:
if (keyCode== KeyEvent.KEYCODE_SYM) {
Log.e("zcfdebug","nowwe catch the bluetooth button action !");
if (down){
Log.e("zcfdebug","nowwe catch the bluetooth button down !");
}
if (up){
Log.e("zcfdebug","nowwe catch the bluetooth button up !");
}
return 1;
}
当然,KEYCODE_SYM是原来系统中已经定义的keycode,其实就是输入法的选择,我们需要屏蔽这个功能,在alps/frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java:
/**
* @hide
*/
public voiddispatchKeyEvent(Context context, int seq, KeyEvent key,
FinishedEventCallback callback) {
booleanhandled = false;
/*zcfdebug--<<
synchronized(mH) {
if(DEBUG) Log.d(TAG, "dispatchKeyEvent");
if(mCurMethod != null) {
if(key.getAction() == KeyEvent.ACTION_DOWN
&& key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
showInputMethodPickerLocked();
handled = true;
}else {
try {
if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
final long startTime = SystemClock.uptimeMillis();
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
return;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId + " dropping: "+ key, e);
}
}
}
}
zcfdebug-->>*/
callback.finishedEvent(seq, handled);
}
注释掉原有功能就好了。
按照我们的项目定义,按键3-5秒为蓝牙状态电源打开搜索功能,长按8秒以上为关闭。关闭的时候,长按8秒没有任何动作。
if (keyCode== KeyEvent.KEYCODE_SYM) {
Log.e("zcfdebug","nowwe catch the bluetooth button action !");
if (down){
Log.e("zcfdebug","nowwe catch the bluetooth button down !");
//lastSymKeyDownTime=System.currentTimeMillis();
lastSymKeyDownTime=event.getEventTime();
}
if (up){
Log.e("zcfdebug","nowwe catch the bluetooth button up !");
SymKeyPressTime=event.getEventTime()-lastSymKeyDownTime;
//SymKeyPressTime=System.currentTimeMillis()-lastSymKeyDownTime;
Log.e("zcfdebug","theSymKeyPressTime is "+SymKeyPressTime);
if(SymKeyPressTime>2000&& SymKeyPressTime<5000){
Log.e("zcfdebug","nowwe catch the bluetooth press 3 second!");
}
if(SymKeyPressTime>7000){
Log.e("zcfdebug","nowwe catch the bluetooth press 8 second!");
}
}
return 1;
}
蓝牙开关等动作,我们在外边的apk程序中实现,我们只要发送intent实现就OK了,代码如下:
if (keyCode== KeyEvent.KEYCODE_SYM) {
Log.e("zcfdebug","nowwe catch the bluetooth button action !");
if (down){
Log.e("zcfdebug","nowwe catch the bluetooth button down !");
//lastSymKeyDownTime=System.currentTimeMillis();
lastSymKeyDownTime=event.getEventTime();
}
if (up){
Log.e("zcfdebug","nowwe catch the bluetooth button up !");
SymKeyPressTime=event.getEventTime()-lastSymKeyDownTime;
//SymKeyPressTime=System.currentTimeMillis()-lastSymKeyDownTime;
Log.e("zcfdebug","theSymKeyPressTime is "+SymKeyPressTime);
if(SymKeyPressTime>2000&& SymKeyPressTime<5000){
Log.e("zcfdebug","nowwe catch the bluetooth press 3 second!");
Intent btStartStopIntent = new Intent(BT_STARTSTOP);
mContext.sendBroadcast(btStartStopIntent);
}
if(SymKeyPressTime>7000){
Log.e("zcfdebug","nowwe catch the bluetooth press 8 second!");
Intent btPairIntent = new Intent(BT_PAIR);
mContext.sendBroadcast(btPairIntent);
}
}
return 1;
}
应用程序如何接收处理intent,将在下一篇文章描述
附录:Howto add a new key on android ICS\ICS2:
[Description]
How to add a new keyon android ICS/ICS2
[Solution]
1.在DCTtool keypad list 文件增加新按键的选项
alps\mediatek\source\dct\Keypad_YuSu.cmp中添加新键,如SMS快捷键
KEY_SYM
KEY_SMS
KEY_0
2.打开DCTtool 在keypad矩阵中在相应定义的按键位中添加新按键,如SMS,然后Save
3.修改linux键盘码文件input.h
由于preloader\uboot\kernel\factory等情况分开使用,相应的文件路径下的input.h都应该修改
为新按键增加键码值
kernel\include\linux\input.h
bionic\libc\kernel\common\linux\input.h
external\kernel-headers\original\linux\input.h
external\qemu\linux_keycodes.h
mediatek\plaform\mt6575\preloader\src\drivers\inc\linux\input.h
Mediatek\plaform\mt6575\uboot\inc\linux\input.h
如KEY_SMS
#define KEY_SMS 252
4.增加keypadlayout文件键盘映射,linux和androidkey映射
mediatek\config\<projectname>\mt6575-kpd.kl
如:
key 252 SMS
其中252是linux键码,SMS是android识别key值如果是需要唤醒系统,还需要增加WAKE
如果新按键是全键盘的一些生僻字符,修改:mediatek\config\<project name>\mt6575-kpd.kcm
5.修改Java识别keycode
framework/base/include/ui/KeyCodelabels.h
KEYCODES数据结构后面增加
{"SMS",220}
framework/base/native/include/android/KeyCodes.h
在按键定义项增加AKEYCODE_SMS = 220;
6.修改Java键盘事件
framework/base/core/java/android/view/keyevent.java
/**
*@hide
*/
public static finalint KEYCODE_SMS =220;
最后的按键为新增的
private static finalint LAST_KEYCODE ==KEYCODE_SMS;
以上/**/注释的code是android非开放API或变量定义的时候,需要添加JavaDoc的识别,否则要运
行makeupdate-api才能build通过
如果是系统按键,修改framework/base/libs/ui/input.cpp
isSystemKey()增加caseAKEYCODE_SMS:
7.修改XML文件描述符framework/base/core/res/res/values/attr.xml
<enumname="KEYCODE_SMS" value="220" />
8.增加测试验证log在android
framework\base\policy\src\com\android\internal\polidy\impl\phoneWindowManager.java
在interceptKeyBeforeDispatching()增加
if(keycode==KeyEvent.KEYCODE_SMS){
log.d(TAG,"interceptKeyTi KEYCODE_SMS keyCode="+ keyCode + "down=" + down + "
repeatCount=" +repeatCount + “ keyguardOn=” + keyguardOn + “ mHomePressed=”+
9.可以抓log确认,或者增加测试APK检测
Kernal log:
<4>[253.828234]kpd:register = fffe ffff ffff ffff ff
<4>[253.828825]kpd:(pressed) HW keycode = 0
<4>[253.829348]kpd:report Linux keycode = 252
<4>[253.829857]kpd:save new keymap state
<4>[254.030814]kpd:register = ffff ffff ffff ffff ff
<4>[254.031405]kpd:(released) HW keycode = 0
<4>[254.031936]kpd:report Linux keycode = 252
<4>[254.032445]kpd:save new keymap state
Android log:
WindowManager:interceptKeyTq keycode=220 screenIsOn=true keyguardActive=false
policyFlags =#2000000 down =false canceled = false
D WindowManager:interceptKeyTi keyCode=220 down=false repeatCount=0 keyguardOn=false
mHomePressed=falsecanceled=false
D WindowManager:interceptKeyTi KEYCODE_SMS keyCode=220 down=false repeatCount=0
keyguardOn=falsemHomePressed=false canceled=false
mtk硬件启动关闭蓝牙功能的项目:mtk 硬件ScanCode和keycode应用示例
原文地址:http://blog.csdn.net/zangcf/article/details/44493623