android模拟按键问题总结[使用IWindowManager.injectKeyEvent方法]

目的:在非源码环境下调用隐藏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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值