前述:
最近公司有个需求,车载项目有个毁密功能,当我们按下毁密键时,会弹出dialog提示框,倒计时5秒后,自动销毁秘钥,今天就来讲讲具体怎么实现。
效果:
思路:
1.物理键实现键值上报
这里因为涉及到底层及驱动比较多,本人不是很懂,是公司同事实现的,我主要是判断当我按下毁密键时,有key值上报上来就可以了。检查key值方法,将手机连上USB之后,adb shell ,再getevent,再按下物理键,就会有键值上报了。
2.键值映射
a.
在.kl键值表文件中添加不重复的键值,键值表一般在Z:\android-4.4.4_r2\devices目录下(也可以到对应项目下去找)。
比如:comip-gpio-keys.kl表下定义了key 183 PROG_BLUE WAKE
比如:comip-gpio-keys.kl表下定义了key 183 PROG_BLUE WAKE
b.在文件frameworks/base/include/ui/keycodeLabels.h中,在后面顺序添加:{ "PROG_RED", 183 }, 需要注意,追加的按键必须在最后的NULL的前面。 在这个地方,会将PROG_RED等这些字符串转换成数值、键值,传送到KeyEvent.java中
c.在frameworks/base/core/res/res/values/attrs.xml中追加: <enum name="KEYCODE_PROG_GRED" value="183" />,同时,需要在frameworks/base/core/java/android/view/KeyEvent.java中添加:public static final int KEYCODE_PROG_RED = 183;
public static final int KEYCODE_DESTROY_KEY = KEYCODE_PROG_RED;
修改完后,需要在根目录下执行make update-api更新current.xml文件,否则编译时会出错。
至此,按键支持添加完毕,就可以在应用程序中响应这些按键了。
3.新键值进行处理:
frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java
case KeyEvent.KEYCODE_DESTROY_KEY: {
if (mGlobalActions != null && mGlobalActions.GlobalActionsDialogIsShown()) {
// GlobalActions will handle PTT key to select poweroff menu.
break;
}
Intent intent = new Intent();
intent.setAction("com.yeezone.destroykey.DestroyKeyReceiver");
if (down) {
intent.putExtra("isUp", 0);
} else {
intent.putExtra("isUp", 1);
}
mContext.sendBroadcast(intent);
if (down) {
mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn, event.getDownTime(),
isImmersiveMode(mLastSystemUiFlags));
ITelephony telephonyService = getTelephonyService();
if (telephonyService != null) {
try {
if (telephonyService.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telephonyService.silenceRinger();
}
} catch (RemoteException ex) {
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
Log.i(TAG, "destroykey down, isScreenOn = " + isScreenOn);
interceptDestroyKeyDown(!isScreenOn);
}
break;
}
这里主要的目的是当我们按下毁密键时,会发送一次广播,同时把按下或者抬起放到action中去。
4.app中定义service接受广播
在这里,我在packages/apps/中新建了一个新的app,用于做毁密程序。DestroyKey.apk
大致分析下这个app,DestroyKeyBroadcastReceiver注册一个重启广播用于激活DestroyKeyService,这个service主要是用来接受framework里发送来的广播。
public void onCreate() {
logd("onCreate~~~~");
super.onCreate();
mHandler = new DialogHandler();
mContext = getApplicationContext();
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
logd("onReceive~~~~");
final String action = intent.getAction();
if (action.equals("com.yeezone.destroykey.DestroyKeyReceiver")) {
int isUp = intent.getIntExtra("isUp", 1);
boolean isDown = (isUp == 0) ? true : false;
logd(isDown + "");
if(isDown){
warningDialing();
}else{
dismissDialog(mDialog,mDestroyKeyDialog);
}
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction("com.yeezone.destroykey.DestroyKeyReceiver");
registerReceiver(mBroadcastReceiver, filter);
}
DestroyKeyDialog.java 重新封装了AlertDialog。
public void showDestroyKeyDialog(){
if(mDialog != null){
mDialog.dismiss();
}
if(mDestroyKeyDialog != null){
mDestroyKeyDialog.dismiss();
}
mDestroyKeyDialog = new DestroyKeyDialog(mContext);
mDestroyKeyDialog.setCanceledOnTouchOutside(false);
mDestroyKeyDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
mDestroyKeyDialog.show();
}
mContext = getApplicationContext();
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG 需要在AndroidManifest配置system权限。
<pre name="code" class="java"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yeezone.destroykey"
android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0" >