android模拟按键问题总结[使用IWindowManager.injectKeyEvent方法]
2013-12-31 14:35
627 查看
目的:在非源码环境下调用隐藏api实现模拟按键的功能。
首先需要下载在android4.0源码环境下编译出来的classes.jar,或者如果你有条件那么可以直接在源码环境下编译(此方法该文不讨论)。
因为我在ubuntu下没能下载完源代码,所以直接采用classes.jar导入到eclipse的方法。
1. classes.jar可以去我的资源中下载classes.jar
2. 有了classes.jar之后,在eclipse界面,拖拉jar进项目的libs目录,使用用户库的方式添加jar
可以参考Android中使用隐藏API(大量图解)
3. 导入之后隐藏的类和方法就能使用了,但是在编译时eclipse有可能会报错:Unable to execute dex: Java heap space
解决方法是修改eclipse.ini:参考博文
4. 更改了之后又可能会遇见eclipse报错: Unable to execute dex: Cannot merge new index 67208 into a non-jumbo instruction!
解决方法:project->clean;清理一下之后重新编译就好了
5. injectKeyEvent的具体用法可以参考:博文
别忘了在项目的manifest文件中添加:sharedUserId和INJECT_EVENTS权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxxx.packagename" android:sharedUserId="android.uid.system" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INJECT_EVENTS" />
添加之后INJECT_EVENTS会报错,此时只要在菜单栏是点project->clean就可以去掉错误然后编译
6. 编译之后直接安装会安装失败,因为没有该apk没有系统权限
解决方法是:下载Signapk工具,可以去我的资源中下载
用法是在命令行下使用命令:java -jar SignApk.jar platform.x509.pem platform.pk8
app_unsigned.apk app_signed.apk
至此,终于在非源码环境下待用了隐藏api实现了模拟按键的功能,辛苦啊。
有任何疑问都可以留言或者发邮件给我263113565@qq.com,或者直接加这个QQ号一起讨论。
=============================分割线=====================================
Q:因为使用原生系统的签名,所以经常有朋友来问我厂商定制的ROM怎么办
A:我后来想到可以使用jni的方法跳过,下面是我找的一些资料,仅仅提供给大家一个更广的思路,这个方法我并没有实现,仅供参考,相信会是个更好的办法
参考一 参考二
#include <stdlib.h> #include <android/log.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/input.h> #include <dirent.h> #include <errno.h> //#include "nativemethod.h" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "EventEmulate", __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "EventEmulate", __VA_ARGS__) #define DEV_DIR "/dev/input" #define sizeof_bit_array(bits) ((bits + 7) / 8) #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) #define ABS_MT_POSITION_X 0x35 #define ABS_MT_POSITION_Y 0x36 struct EVENT_INFO { int fd_touch; int fd_key; int screen_width; int screen_height; int abs_x_min; int abs_x_max; int abs_y_min; int abs_y_max; }; int scan_dir(const char *dirname); int open_dev(const char *deviceName); int write_event(int fd, int type, int code, int value); void calculateXY(float x, float y, int *abs_x, int *abs_y); int containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex); struct EVENT_INFO ei; int initEVT = 0; int EVT_open(struct NATIVE_INFO *info) { struct input_absinfo absinfo; if(initEVT) return 0; if(info == NULL) { LOGE("info null point."); goto fail; } if(info->FB_width == 0 || info->FB_height == 0) { LOGE("error width %d and height %d.", info->FB_width, info->FB_height); goto fail; } memset(&ei, 0, sizeof(ei)); ei.screen_width = info->FB_width; ei.screen_height = info->FB_height; scan_dir(DEV_DIR); if(ioctl(ei.fd_touch, EVIOCGABS(ABS_X), &absinfo)) { LOGI("Error reading absolute controller ABS_X[%d]: %s", errno, strerror(errno)); return; } ei.abs_x_min = absinfo.minimum; ei.abs_x_max = absinfo.maximum; if(ioctl(ei.fd_touch, EVIOCGABS(ABS_Y), &absinfo)) { LOGI("Error reading absolute controller ABS_Y[%d]: %s", errno, strerror(errno)); return; } ei.abs_y_min = absinfo.minimum; ei.abs_y_max = absinfo.maximum; initEVT = 1; return 0; fail: EVT_close(); return -1; } int EVT_close() { if(ei.fd_key > 0) close(ei.fd_key); if(ei.fd_touch > 0) close(ei.fd_touch); initEVT = 0; return 0; } int EVT_touch(int action, float x, float y) { int abs_x, abs_y; if(initEVT == 0) { LOGE("event not inital"); return -1; } switch(action) { case ACTION_DOWN: calculateXY(x, y, &abs_x, &abs_y); write_event(ei.fd_touch, 3, 0, abs_x); write_event(ei.fd_touch, 3, 1, abs_y); write_event(ei.fd_touch, 1, 330, 1); write_event(ei.fd_touch, 0, 0, 0); break; case ACTION_UP: write_event(ei.fd_touch, 1, 330, 0); write_event(ei.fd_touch, 0, 0, 0); break; case ACTION_MOVE: calculateXY(x, y, &abs_x, &abs_y); write_event(ei.fd_touch, 3, 0, abs_x); write_event(ei.fd_touch, 3, 1, abs_y); write_event(ei.fd_touch, 0, 0, 0); break; } return 0; } int EVT_key(int action, int key) { if(initEVT == 0) { LOGE("event not inital"); return -1; } switch(action) { case ACTION_DOWN: write_event(ei.fd_key, 1, key, 1); break; case ACTION_UP: write_event(ei.fd_key, 1, key, 0); break; } return 0; } int scan_dir(const char *dirname) { char devname[PATH_MAX]; char *filename; DIR *dir; struct dirent *de; dir = opendir(dirname); if(dir == NULL) return -1; strcpy(devname, dirname); filename = devname + strlen(devname); *filename++ = '/'; while((de = readdir(dir))) { if(de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) continue; strcpy(filename, de->d_name); open_dev(devname); } closedir(dir); return 0; } int open_dev(const char *deviceName) { int fd; int version; uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)]; uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)]; fd = open(deviceName, O_RDWR); if(fd < 0) { LOGI("could not open device[%d]: %s", errno, strerror(errno)); return -1; } if(ioctl(fd, EVIOCGVERSION, &version)) { return -1; } memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) { if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD), sizeof_bit_array(BTN_DIGI)) || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK), sizeof_bit_array(KEY_MAX + 1))) { ei.fd_key = fd; LOGI("get key input device: %s", deviceName); } } memset(abs_bitmask, 0, sizeof(abs_bitmask)); if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) { // Is this a new modern multi-touch driver? if (test_bit(ABS_MT_POSITION_X, abs_bitmask) && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) { ei.fd_touch = fd; LOGI("get multi-touch input device: %s", deviceName); // Is this an old style single-touch driver? } else if (test_bit(BTN_TOUCH, key_bitmask) && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) { ei.fd_touch = fd; LOGI("get single-touch input device: %s", deviceName); } } } int write_event(int fd, int type, int code, int value) { struct input_event event; memset(&event, 0, sizeof(event)); event.type = type; event.code = code; event.value = value; if(write(fd, &event, sizeof(event)) < sizeof(event)) { LOGI("write event failed[%d]: %s", errno, strerror(errno)); return -1; } return 0; } void calculateXY(float x, float y, int *abs_x, int *abs_y) { *abs_x = ei.abs_x_min + (int)((x * (float)(ei.abs_x_max - ei.abs_x_min)) / ei.screen_width + 0.5); *abs_y = ei.abs_y_min + (int)((y * (float)(ei.abs_y_max - ei.abs_y_min)) / ei.screen_height + 0.5); } int containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) { const uint8_t* end = array + endIndex; array += startIndex; while (array != end) { if (*(array++) != 0) { return 1; } } return 0; }
相关文章推荐
- android模拟按键问题总结[使用IWindowManager.injectKeyEvent方法](转)
- android模拟按键问题总结[使用IWindowManager.injectKeyEvent方法]
- IWindowManager.injectKeyEvent模拟按键
- IWindowManager.injectKeyEvent模拟按键
- 转:Android随笔之——使用Root权限实现后台模拟全局按键、触屏事件方法(类似按键精灵)
- 使用dispatchKeyEvent onkeyevent return true没得按键音问题
- Android学习总结一:adb的使用、打电话、Button监听两种方法、发短信、ADT23.0.2版本兼容问题
- Android中使用代码截图的各种方法总结
- Android Library Project 使用问题总结
- Android Library Project 使用问题总结
- Android解决Fragment使用replace方法重叠问题
- 使用split()遇到的问题和方法总结 ( Dangling meta character 和 多个分隔字符)
- android ListView组件使用常见问题或形式总结(一)
- Android使用HttpClient方法和易错问题
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- android中使用BitmapFactory的decodeStream()方法解码图片失败问题
- Android关于PagerAdapter的使用方法的总结
- Android使用multidex解决方法数越界问题65536
- Android 使用adb shell命令时出现sqlite3 : not found 问题 解决方法
- Android Butterknife 8.4.0 使用方法总结