android 使用uinput模拟输入设备的方法

在google remote中,android接收端接收socket发来的IR CODE,然后将IR CODE模拟出来发给系统处理,这就是google remote接收端的原理。

系统端怎样模拟input event呢?
方法一:通过Instrumentation.sendKeyDownUpSync 实现,简单使用但是问题在于sendKeyDownUpSync发出的event,无法运行到
interceptKeyBeforeDispatching,也就无法正常作用 HOME,VOL...
方法二:通过uinput桥接;原理是利用内核现有的uinput驱动,通过内核驱动uinput来发送input event,而且还容易使用kl,kcm 客制化;

经过比较方法二较优,下面就就给出方法二的测试代码...
  1、main函数,setup_uinput_device 完成设备的注册,然后创建一个线程 VirtualInputDev_EventThread,该线程重复发出keycode;

代码如下:

int main()
{

printf("Enter process !!!! \n");

stVirtualInputDevData *pKpdData = (stVirtualInputDevData*) malloc(sizeof(stVirtualInputDevData));
   pKpdData->min_keycode = umin_keycode;
   pKpdData->max_keycode = umax_keycode;
    if (setup_uinput_device(pKpdData) < 0) {
        printf("Unable to find uInput device\n");
        free(pKpdData);
        return -1;
    }

pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (0 != pthread_create(&keypad_EventThreadId, &attr, VirtualInputDev_EventThread, (void *)0)) {
        printf("Create KeypadEventThread Failed!!\n");
        exit(1);
    }

// Coverity server need set to ignore this.
    while (1) {
        usleep(1000000);  // sleep 1 second
    }

free(pKpdData);
    pKpdData = 0;

// Destroy the device
    ioctl(uinp_fd, UI_DEV_DESTROY);

close(uinp_fd);
    return 0;
}

2、setup_uinput_device函数,完成设备注册;可以看到是直接打开uinput节点,设置了虚拟设备的name,verdor,product,bustype,
   最后通过ioctl(uinp_fd, UI_DEV_CREATE)注册设备

代码如下:

int setup_uinput_device(stVirtualInputDevData* mstVirtualInputDevData)
{
    struct uinput_user_dev uinp; // uInput device structure
    int i;

// Open the input device
    uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
    if (uinp_fd == 0) {
        printf("Unable to open /dev/uinput\n");
        return -1;
    }

// Intialize the uInput device to NULL
    memset(&uinp, 0x00, sizeof(uinp));
    strncpy(uinp.name, "virtualinputdev", sizeof(uinp.name)-1);
    uinp.id.vendor = 0x1341;
    uinp.id.product = 0x0001;
    uinp.id.bustype = BUS_VIRTUAL;

// Keyboard
    ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
    for (i = mstVirtualInputDevData->min_keycode; i < mstVirtualInputDevData->max_keycode; i++) {
        ioctl(uinp_fd, UI_SET_KEYBIT, i);
    }

// Create input device into input sub-system
    if (write(uinp_fd, &uinp, sizeof(uinp)) != sizeof(uinp)) {
        printf("First write returned fail.\n");
        return -1;
    }

if (ioctl(uinp_fd, UI_DEV_CREATE)) {
        printf("ioctl UI_DEV_CREATE returned fail.\n");
        return -1;
    }

return 1;
}

3、线程 VirtualInputDev_EventThread,只是重复发key,发key是通过write_event_to_device来完成的

代码如下:

static void* VirtualInputDev_EventThread(void *driver_data)
{

unsigned char u8Keycode,i=umin_keycode;

while (1) {
        u8Keycode = 0xff;

/* sleep an interval time */
        usleep(2000000);//sleep 5 s
        /* fill event to uinput device. */
        write_event_to_device(i++, 0);
  if(i==4){
  i = 0;
  }
  printf ("virtualinputdev thread ...\n");
  //i %= umax_keycode;
    }

printf ("virtualinputdev thread died\n");
    pthread_exit(0);
    return 0;
}

4、write_event_to_device 写event到uinput节点

代码如下:

void write_event_to_device(unsigned char u8KeyCode, unsigned char u8Repeat)
{
    struct input_event event; // Input device structure
    struct timespec s;
    s.tv_nsec = 5000000L;
    s.tv_sec = 0;

memset(&event, 0x00, sizeof(event));
    gettimeofday(&event.time, 0);
    event.type = EV_KEY;
    event.code = u8KeyCode;
    event.value = 1;
    write(uinp_fd, &event, sizeof(event));

memset(&event, 0x00, sizeof(event));
    gettimeofday(&event.time, 0);
    event.type = EV_KEY;
    event.code = u8KeyCode;
    event.value = 0;
    write(uinp_fd, &event, sizeof(event));

memset(&event, 0x00, sizeof(event));
    gettimeofday(&event.time, 0);
    event.type = EV_SYN;
    event.code = SYN_REPORT;
    event.value = 0;
    write(uinp_fd, &event, sizeof(event));
}

(0)

相关推荐

  • Android手机获取IP地址的两种方法

    1.使用WIFI 首先设置用户权限 复制代码 代码如下: <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>  <

  • android 获取本机的IP地址和mac物理地址的实现方法

    获取本机IP地址 public String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(android.content.Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int ipAddress = wifiInfo.getIpAddress(); try { return In

  • Android中获取设备的各种信息总结

    一.屏幕分辨率 Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y; 或者: DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getM

  • 设置Android设备WIFI在休眠时永不断开的代码实现

    MainActivity如下: package cc.ab; import android.os.Bundle; import android.provider.Settings; import android.app.Activity; /** * Demo描述: * 设置设备在睡眠期间始终保持WLAN开启. * * 参考资料: * 1 http://stackoverflow.com/questions/8652031/how-to-modify-wi-fi-sleep-policy-pro

  • Android编程获取设备MAC地址的实现方法

    本文实例讲述了Android编程获取设备MAC地址的实现方法.分享给大家供大家参考,具体如下: /** * 获取设备的mac地址 * * @param ac * @param callback * 成功获取到mac地址之后会回调此方法 */ public static void getMacAddress(final Activity ac, final SimpleCallback callback) { final WifiManager wm = (WifiManager) ac .get

  • android实现获取有线和无线Ip地址的方法

    本文实例讲述了android实现获取有线和无线Ip地址的方法.分享给大家供大家参考.具体如下: 做android的开发时,遇到了获取有线ip地址的问题.不多说 上代码! for (Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); if (intf.getNam

  • asp.net 通过UserAgent判断智能设备(Android,IOS)

    最近一直在升级公司的手机站点,出了个触屏版专用的,做好后,就尝试通过 Agent 来判断相应的智能手机设备,然后跳转到新的手机站点经过不懈的努力,终于搜集了比较全的 智能设备 的 Agent,然后又写了程序,直接上代码吧 ,希望能帮助到你 复制代码 代码如下: /// <summary> /// 根据 Agent 判断是否是智能手机 /// </summary> /// <returns></returns> public static bool Check

  • 使用User Agent分辨出Android设备类型的安全做法

    随着Android设备增多,不少网站都开始设备Android设备,而Android主流设备类型以手机和平板为主.网站在适配时通过User Agent(用户代理,以下简称UA)又如何区分呢,本文部分内容翻译自Google官方博客Mo' better to also detect "mobile" user-agent. 一针见血 标准判断规则:Mobile Android has "Mobile" string in the User-Agent header. Ta

  • python获取android设备的GPS信息脚本分享

    在android上,我们可以使用QPython来编写.执行Python脚本.它对很多android 系统函数进行了方便的封装,使用QPython编写功能简单的小程序异常方便. 这个示例是我之前用来读取手机位置信息并作为进一步处理数据的基础脚本. 复制代码 代码如下: # -*- coding: utf-8 -*- import androidhelper import time from math import radians droid = androidhelper.Android() dr

  • android手机获取gps和基站的经纬度地址实现代码

    复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" an

  • Android中修改设备权限的方法

    本文实例讲述了Android中修改设备权限的方法.分享给大家供大家参考.具体如下: 有时我们编写了驱动后,在上层程序中要访问设备,但android代码编译后的设备权限是root的,其他用户不可访问(包括system),只是就需要在android源码中将设备的权限修改下. 具体的修改位置为源码的system/core/init/devices.c文件中static struct perms_ devperms[]的定义中,如添加设备hidraw0的权限,只需添加一行: 复制代码 代码如下: { "

  • Android 进入设备后台data文件夹的办法

    大家都知道,我们在进行android项目开发时,当涉及到需要存取数据,也就是需要进行数据的互动时,我们就需要把数据存放在虚拟设备的data 文件夹中.之前在相关书籍中了解到如何把文件上传到设备,如前面所说的mp3,mp4播放器中需要上传到设备中的音频及视频文件.方法如下:C:> adb push c:codesamplevideo.mp4 /data/samplevideo.mp4 今天在网上无意中又了解到了如何进入设备的后台的命令,希望对大家有帮助. 可以使用 adb shell 进入设备后台

  • Android中查看USB连接的外接设备信息的代码实例

    1,USB存储设备(如:U盘,移动硬盘): //USB存储设备 插拔监听与 SD卡插拔监听一致. 复制代码 代码如下: private USBBroadCastReceiver mBroadcastReceiver; IntentFilter iFilter = new IntentFilter();       iFilter.addAction(Intent.ACTION_MEDIA_EJECT);       iFilter.addAction(Intent.ACTION_MEDIA_MO

随机推荐