记得以前在做一个C++项目时,需要在某一步操作之后人为用代码模拟敲键盘上的回车键(Enter)效果。

  出于好奇,这几天研究了一下Android中手机(或平板)上各种按键的键值、模拟方法及最终效果。

  1、先来看看Android中对按键和值的定义方式:

  1. public static final int KEYCODE_UNKNOWN = 0;
  2. /** Key code constant: Soft Left key. */
  3. public static final int KEYCODE_SOFT_LEFT = 1;
  4. /** Key code constant: Soft Right key. */
  5. public static final int KEYCODE_SOFT_RIGHT = 2;
  6. /** Key code constant: Home key. */
  7. public static final int KEYCODE_HOME = 3;
  8. /** Key code constant: Back key. */
  9. public static final int KEYCODE_BACK = 4;
  10. /** Key code constant: Call key. */
  11. public static final int KEYCODE_CALL = 5;
  12. /** Key code constant: End Call key. */
  13. public static final int KEYCODE_ENDCALL = 6;
  14. /** Key code constant: '0' key. */
  15. public static final int KEYCODE_0 = 7;
  16. /** Key code constant: '1' key. */
  17. public static final int KEYCODE_1 = 8;
  18. /** Key code constant: '2' key. */
  19. public static final int KEYCODE_2 = 9;
  20. /** Key code constant: '3' key. */
  21. public static final int KEYCODE_3 = 10;
  22. /** Key code constant: '4' key. */
  23. public static final int KEYCODE_4 = 11;
  24. /** Key code constant: '5' key. */
  25. public static final int KEYCODE_5 = 12;
  26. /** Key code constant: '6' key. */
  27. public static final int KEYCODE_6 = 13;
  28. /** Key code constant: '7' key. */
  29. public static final int KEYCODE_7 = 14;
  30. /** Key code constant: '8' key. */
  31. public static final int KEYCODE_8 = 15;
  32. /** Key code constant: '9' key. */
  33. public static final int KEYCODE_9 = 16;
  34. /** Key code constant: '*' key. */
  35. public static final int KEYCODE_STAR = 17;
  36. /** Key code constant: '#' key. */
  37. public static final int KEYCODE_POUND = 18;
  38. /** Key code constant: Directional Pad Up key.
  39. * May also be synthesized from trackball motions. */
  40. public static final int KEYCODE_DPAD_UP = 19;
  41. /** Key code constant: Directional Pad Down key.
  42. * May also be synthesized from trackball motions. */
  43. public static final int KEYCODE_DPAD_DOWN = 20;
  44. /** Key code constant: Directional Pad Left key.
  45. * May also be synthesized from trackball motions. */
  46. public static final int KEYCODE_DPAD_LEFT = 21;
  47. /** Key code constant: Directional Pad Right key.
  48. * May also be synthesized from trackball motions. */
  49. public static final int KEYCODE_DPAD_RIGHT = 22;
  50. /** Key code constant: Directional Pad Center key.
  51. * May also be synthesized from trackball motions. */
  52. public static final int KEYCODE_DPAD_CENTER = 23;
  53. /** Key code constant: Volume Up key.
  54. * Adjusts the speaker volume up. */
  55. public static final int KEYCODE_VOLUME_UP = 24;
  56. /** Key code constant: Volume Down key.
  57. * Adjusts the speaker volume down. */
  58. public static final int KEYCODE_VOLUME_DOWN = 25;
  59. /** Key code constant: Power key. */
  60. public static final int KEYCODE_POWER = 26;
  61. /** Key code constant: Camera key.
  62. * Used to launch a camera application or take pictures. */
  63. public static final int KEYCODE_CAMERA = 27;
  64. /** Key code constant: Clear key. */
  65. public static final int KEYCODE_CLEAR = 28;
  66. /** Key code constant: 'A' key. */
  67. public static final int KEYCODE_A = 29;
  68. /** Key code constant: 'B' key. */
  69. public static final int KEYCODE_B = 30;
  70. /** Key code constant: 'C' key. */
  71. public static final int KEYCODE_C = 31;
  72. /** Key code constant: 'D' key. */
  73. public static final int KEYCODE_D = 32;
  74. /** Key code constant: 'E' key. */
  75. public static final int KEYCODE_E = 33;
  76. /** Key code constant: 'F' key. */
  77. public static final int KEYCODE_F = 34;
  78. /** Key code constant: 'G' key. */
  79. public static final int KEYCODE_G = 35;
  80. /** Key code constant: 'H' key. */
  81. public static final int KEYCODE_H = 36;
  82. /** Key code constant: 'I' key. */
  83. public static final int KEYCODE_I = 37;
  84. /** Key code constant: 'J' key. */
  85. public static final int KEYCODE_J = 38;
  86. /** Key code constant: 'K' key. */
  87. public static final int KEYCODE_K = 39;
  88. /** Key code constant: 'L' key. */
  89. public static final int KEYCODE_L = 40;
  90. /** Key code constant: 'M' key. */
  91. public static final int KEYCODE_M = 41;
  92. /** Key code constant: 'N' key. */
  93. public static final int KEYCODE_N = 42;
  94. /** Key code constant: 'O' key. */
  95. public static final int KEYCODE_O = 43;
  96. /** Key code constant: 'P' key. */
  97. public static final int KEYCODE_P = 44;
  98. /** Key code constant: 'Q' key. */
  99. public static final int KEYCODE_Q = 45;
  100. /** Key code constant: 'R' key. */
  101. public static final int KEYCODE_R = 46;
  102. /** Key code constant: 'S' key. */
  103. public static final int KEYCODE_S = 47;
  104. /** Key code constant: 'T' key. */
  105. public static final int KEYCODE_T = 48;
  106. /** Key code constant: 'U' key. */
  107. public static final int KEYCODE_U = 49;
  108. /** Key code constant: 'V' key. */
  109. public static final int KEYCODE_V = 50;
  110. /** Key code constant: 'W' key. */
  111. public static final int KEYCODE_W = 51;
  112. /** Key code constant: 'X' key. */
  113. public static final int KEYCODE_X = 52;
  114. /** Key code constant: 'Y' key. */
  115. public static final int KEYCODE_Y = 53;
  116. /** Key code constant: 'Z' key. */
  117. public static final int KEYCODE_Z = 54;

  其实,在源文件KeyEvent.java中总共定义了将近个键值,这里只给出了个(BackHome数字大写字母等)。

  2、而要在程序代码中模拟按键的作用,最好是结合线程一起使用,否则有些按键在模拟过程中会出现程序异常终止的情况。

  如返回键Back,键值为,若是直接模拟,就会运行即终止。代码很简单,只需要两句:

  1. Instrumentation inst = new Instrumentation();
  2. inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);

  InstrumentationActivity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的。

  我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。

  3、接下来,老老实实利用线程(Thread)来实现按键的模拟效果,当然还用到了消息机制(HandlerMessage):

  a、首先在onCreate()方法之前定义Handler对象handler

  1. Handler handler;

  b、之后在onCreate方法中定义线程并启动,

  1. Thread t = new Thread() {
  2. public void run() {
  3. Looper.prepare();
  4. handler = new Handler() {
  5.   public void handleMessage(Message msg) {
  6. Instrumentation inst = new Instrumentation();
  7. //inst.sendCharacterSync(msg.what);
  8. inst.sendKeyDownUpSync(msg.what);
  9. }
  10. };
  11. Looper.loop();
  12. }
  13. };
  14. t.start();

  注意上述代码中的注释部分,实践证明两种方法(sendCharacterSync(int keycode)sendKeyDownUpSync(int keycode))都可以达到预期的效果。

  c、线程开启了,就差发送带按键值的消息了,在执行代码块中添加以下代码即可,

  1. Message msg = new Message();
  2. //msg.what = KeyEvent.KEYCODE_BACK;
  3. String s = key_value.getText().toString();
  4. if(!("".equals(s)) && s.matches("^[0-9]*$")){
  5. msg.what = Integer.parseInt(s);
  6. handler.sendMessage(msg);
  7. }
  8. else{
  9. Toast.makeText(getApplicationContext(),"please input a right keycde",Toast.LENGTH_SHORT).show();
  10. 10 }

  这里键值是附带在消息对象的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 implementation for key events that should be handled normally.

  5、下面给出一个比较容易的替代方案,虽然比较山寨,效果还行:

  1. @Override
  2. public boolean onKeyDown(int keyCode, KeyEvent event) {
  3. if(keyCode == KeyEvent.KEYCODE_BACK){
  4. Intent intent = new Intent(Intent.ACTION_MAIN);
  5. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  6. intent.addCategory(Intent.CATEGORY_HOME);
  7. this.startActivity(intent);
  8. return true;
  9. }
  10. return super.onKeyDown(keyCode, event);
  11. }

  需要注意的是,ACTIONCATEGORY的设置和AndroidManifest.xml文件中一致,

  标志位设置为Intent.FLAG_ACTIVITY_NEW_TASK,如果不是,则不是以一个新任务的角色生成,会出现问题。

Android应用程序模拟手机按键的更多相关文章

  1. ADB——模拟手机按键输入

    基本命令 adb 模拟按键输入的命令主要通过 input 进行 Usage: input [<source>] <command> [<arg>...] The s ...

  2. 【python-appium】模拟手机按键搜索异常

    执行代码的过程中运行self.driver.press_keycode(84)设备没反映,则需要关闭#desired_caps["unicodeKeyboard"] = " ...

  3. Android 推断程序在手机中是否是活动状态或者正在执行状态

    沈阳斌子在今天项目需求上碰到个这种问题,在Service中须要推断当前的程序是否是活动状态,换句话说也就是说后台跑的服务中有业务需求检測当前程序是否是该服务的程序 这样好让点击推送通知时跳转到不同的页 ...

  4. Android应用程序键盘(Keyboard)消息处理机制分析

    在Android系统中,键盘按键事件是由WindowManagerService服务来管理的,然后再以消息的形 式来分发给应用程序处理,不过和普通消息不一样,它是由硬件中断触发的:在上一篇文章< ...

  5. 转:Android随笔之——使用Root权限实现后台模拟全局按键、触屏事件方法(类似按键精灵)

    本文转载自CSDN的jzj1993,原文连接:http://blog.csdn.net/jzj1993/article/details/39158865 有时我们需要使用安卓实现在后台模拟系统按键,比 ...

  6. Android adb 模拟滑动 按键 点击事件

    模拟事件全部是通过input命令来实现的,首先看一下input命令的使用: usage: input ... input text <string>       input keyeven ...

  7. Android随笔之——用shell脚本模拟用户按键、触摸操作

    之前写过两篇关于Android中模拟用户操作的博客(其实用一篇是转载的),现在就来讲讲用shell脚本来模拟用户按键操作.本次的目标是用shell脚本打开微信并在其搜索框中搜索相关内容. 本文的模拟功 ...

  8. Android随笔之——模拟按键操作的几种方式

    前几天转过一篇Android上模拟按键操作.触屏事件的博客,昨天又去找了百度.谷歌了一下,写了一点简单的测试代码,留待不时之需.有需要看之前转载的那篇博客的请看这里→_→转:Android随笔之——使 ...

  9. 解决小米手机不能运行Android Studio程序的问题

    转载自:解决小米手机不能运行Android Studio程序的问题 问题描述 Android Studio升级到2.3版本之后,小米手机MIUI8不能运行Android Studio程序,报如下错误: ...

随机推荐

  1. MyCat 学习笔记 第九篇.数据分片 之 数值分布

    1 应用场景 Mycat 自带了多套数据分片的机制,其实根据数值分片也是比较简单,其实这个和数据取摸是类似的实现. 优.缺点同上一篇 2 环境说明 参考  <MyCat 学习笔记>第六篇. ...

  2. js中location.href的用法

    Javascript中的location.href有很多种用法,主要如下: self.location.href="/url" 当前页面打开URL页面 ocation.href=& ...

  3. 如何定制你自己的jQuery

    jQuery随着版本的不断升级代码量也随之增加,从1.0.0的不到两千行到现在的1.10.2已经突破1万行. 新的API不断增加,但有些在项目中并没有用到.jQuery团队很早就考虑到这一点,按模块来 ...

  4. Hadoop with tool interface

    Often Hadoop jobsare executed through a command line. Therefore, each Hadoop job has to support read ...

  5. Java Consumer and Producer demo

    import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; class producer {     Rando ...

  6. JavaScript的执行上下文

    在JavaScript的运行过程中,经常会遇到一些"奇怪"的行为,不理解为什么JavaScript会这么工作. 这时候可能就需要了解一下JavaScript执行过程中的相关内容了. ...

  7. JavaScript的几种函数的结构形式

    匿名函数,普通函数,变量函数,基于对象的方法 介绍它们的优劣点(性能,执行条件,可维护性,适合大型还是小型) Javascript有着灵活多变的函数方法,具体选用何种形式,都会极大地影响应用程序的编写 ...

  8. 【读书笔记《Android游戏编程之从零开始》】14.游戏开发基础(Bitmap 位图的渲染与操作)

    Bitmap 是图形类,Android 系统支持的图片格式有 png.jpg.bmp 等. 对位图操作在游戏中是很重要的知识点,比如游戏中需要两张除了大小之外其他完全相同的图,那么如果会对位图进行缩放 ...

  9. leetcode-Single NumberII

    https://leetcode.com/problems/single-number-ii/ 很无耻的又一次使用了黑暗料理... class Solution: # @param {integer[ ...

  10. JavaWeb学习----JSTL标签库

    一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...