** Key code constant: 'I' key. */
public static final int KEYCODE_I? ? ? ? ? ? ? = 37;
/** Key code constant: 'J' key. */
public static final int KEYCODE_J? ? ? ? ? ? ? = 38;
/** Key code constant: 'K' key. */
public static final int KEYCODE_K? ? ? ? ? ? ? = 39;
/** Key code constant: 'L' key. */
public static final int KEYCODE_L? ? ? ? ? ? ? = 40;
/** Key code constant: 'M' key. */
public static final int KEYCODE_M? ? ? ? ? ? ? = 41;
/** Key code constant: 'N' key. */
public static final int KEYCODE_N? ? ? ? ? ? ? = 42;
/** Key code constant: 'O' key. */
public static final int KEYCODE_O? ? ? ? ? ? ? = 43;
/** Key code constant: 'P' key. */
public static final int KEYCODE_P? ? ? ? ? ? ? = 44;
/** Key code constant: 'Q' key. */
public static final int KEYCODE_Q? ? ? ? ? ? ? = 45;
/** Key code constant: 'R' key. */
public static final int KEYCODE_R? ? ? ? ? ? ? = 46;
/** Key code constant: 'S' key. */
public static final int KEYCODE_S? ? ? ? ? ? ? = 47;
/** Key code constant: 'T' key. */
public static final int KEYCODE_T? ? ? ? ? ? ? = 48;
/** Key code constant: 'U' key. */
public static final int KEYCODE_U? ? ? ? ? ? ? = 49;
/** Key code constant: 'V' key. */
public static final int KEYCODE_V? ? ? ? ? ? ? = 50;
/** Key code constant: 'W' key. */
public static final int KEYCODE_W? ? ? ? ? ? ? = 51;
/** Key code constant: 'X' key. */
public static final int KEYCODE_X? ? ? ? ? ? ? = 52;
/** Key code constant: 'Y' key. */
public static final int KEYCODE_Y? ? ? ? ? ? ? = 53;
/** Key code constant: 'Z' key. */
public static final int KEYCODE_Z? ? ? ? ? ? ? = 54;
其实,在源文件KeyEvent.java中总共定义了将近260个键值,这里只给出了27个(Back、Home、数字、大写字母等)。
2、而要在程序代码中模拟按键的作用,最好是结合线程一起使用,否则有些按键在模拟过程中会出现程序异常终止的情况。
如返回键Back,键值为4,若是直接模拟,就会运行即终止。代码很简单,只需要两句:
Instrumentation inst = new Instrumentation();
?inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的。
我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。
3、接下来,老老实实利用线程(Thread)来实现按键的模拟效果,当然还用到了消息机制(Handler、Message):
a、首先在onCreate()方法之前定义Handler对象handler,
Handler handler;
b、之后在onCreate方法中定义线程并启动,
?Thread t = new Thread() {
? ? public void run() {
? ? ? ? Looper.prepare();
? ? ? ? handler = new Handler() {
? ? ? ? public void handleMessage(Message msg) {
? ? ? ? ? ? ? Instrumentation inst = new Instrumentation();
? ? ? ? ? ? ? //inst.sendCharacterSync(msg.what);
? ? ? ? ? ? ? inst.sendKeyDownUpSync(msg.what);
? ? ? ? ? }
? ? ? ? };
? ? ? ? Looper.loop();
? ? }
};
t.start();
注意上述代码中的注释部分,实践证明两种方法(sendCharacterSync(int keycode),sendKeyDownUpSync(int keycode))都可以达到预期的效果。
c、线程开启了,就差发送带按键值的消息了,在执行代码块中添加以下代码即可,
?Message msg = new Message();
//msg.what = KeyEvent.KEYCODE_BACK;
String s = key_value.getText().toString();
if(!("".equals(s)) && s.matches("^[0-9]*$")){
? msg.what = Integer.parseInt(s);
? handler.sendMessage(msg);
}
else{
? Toast.makeText(getApplicationContext(),"please input a right keycde",Toast.LENGTH_SHORT).show();
}
这里键值是附带在消息对象的what成员身上的,实现方法很多种,这里不一一给出了。
可以看到,代码中注释部分是将键值固定了:
msg.what = KeyEvent.KEYCODE_BACK;
这样做不管是调试,还是以后运行应用程序来模拟按键,都不太实用,每次都要重新设定并运行程序。
所以,本程序采用后面一种方式:
在主界面上多定义一个编辑框组件key_value,模拟之前输入想要的键值即可(需要将键值由输入的String型转为int型)。
当然,前提是需要对??键与对应的值有个大致的了解,而且,在发送消息之前需要对输入的键值进行空与整型的合法性判断,否则会出现难以察觉的异常。
4、经过测试,发现一些按键是不能通过模拟来达到真实效果的。
如Home键,官方给出的文档显示:Home键不再对一般应用允许模拟,即设置了权限。
和手机全屏截取API类似,需要System级或者Root级应用才可以实现想要的效果。
其所给出的替代方案也行不通:Called to process key events. You can override this to intercept all key events before they are dispatched to the window. Be? sure to call this implemen