zoukankan      html  css  js  c++  java
  • 使用JNI封装底层input系统提供的event事件

      首先说下思路,本文采用jni技术封装底层触摸事件,封装成MotionEvent类一样,不过没有android系统MotionEvent强大。源码MotionEvent位置:java-->frameworks/base/core/java/android/view/MotionEvent.java     ; jni-->frameworks/base/core/jni/android_view_MotionEvent.cpp  原有的MotionEvent封装的事件之多,我所做的就是只封装红外触摸屏所产生的几个简单事件,例如坐标事件以及触摸宽度等等。

      1)底层事件来源于/dev/input/event。

      2)顶层事件采用java封装为类。

      3)jni中使用到了线程 和 管道,最开始打算使用线程和消息队列,可是失败了,android不支持消息队列。

                                            

    直接上代码:

    java上层封装代码

     1 package android.wf;
     2 public final class MotionEvent {
     3 
     4     public MotionEvent(){
     5         int fd = initEvent();
     6         System.out.println("fd = %d
    ");
     7     }
     8     
     9     public final float getX() {
    10         return getXX();
    11     }
    12     
    13     public final float getY() {
    14        return getYY();
    15     }
    16     
    17     public final float getWidth() {
    18            return getH();
    19     }
    20     
    21     public final float getHight() {
    22            return getW();
    23     }
    24     
    25     static
    26     {
    27            System.loadLibrary("MotionEvent");
    28     }
    29     
    30     private static native float getW();
    31     private static native float getH();
    32     private static native int initEvent();
    33     private static native float getXX();
    34     private static native float getYY();
    35     
    36 }

    使用javah编译生成CPP的头文件:

     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include <jni.h>
     3 /* Header for class android_wf_MotionEvent */
     4 
     5 #ifndef _Included_android_wf_MotionEvent
     6 #define _Included_android_wf_MotionEvent
     7 #ifdef __cplusplus
     8 extern "C" {
     9 #endif
    10 /*
    11  * Class:     android_wf_MotionEvent
    12  * Method:    initEvent
    13  * Signature: ()F
    14  */
    15 JNIEXPORT jint JNICALL Java_android_wf_MotionEvent_initEvent
    16   (JNIEnv *, jclass);
    17 
    18 /*
    19  * Class:     android_wf_MotionEvent
    20  * Method:    getXX
    21  * Signature: ()F
    22  */
    23 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getXX
    24   (JNIEnv *, jclass);
    25 
    26 /*
    27  * Class:     android_wf_MotionEvent
    28  * Method:    getYY
    29  * Signature: ()F
    30  */
    31 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getYY
    32   (JNIEnv *, jclass);
    33 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getW
    34   (JNIEnv *, jclass);
    35 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getH
    36 (JNIEnv *, jclass );
    37 #ifdef __cplusplus
    38 }
    39 #endif
    40 #endif

    接着在CPP文件中实现java的native函数:

      1 #include <linux/input.h>
      2 #include <stdio.h>
      3 #include <pthread.h>
      4 #include <unistd.h>
      5 #include <stdlib.h>
      6 #include <sys/types.h>
      7 #include <string.h>
      8 #include <sys/stat.h>
      9 #include <fcntl.h>
     10 #include <jni.h>
     11 #include "android_wf_MotionEvent.h"
     12 #include<android/log.h>
     13 
     14 //LCD和触摸框转换比例
     15 float xScale = 1920.0/32768;
     16 float yScale = 1080.0/32768;
     17 
     18 int fd ; // dev的文件描述符
     19 int fds[2];  //管道
     20 
     21 jfloat x;
     22 jfloat y;
     23 jfloat pressure;
     24 jfloat touchMajor;
     25 jfloat touchMinor; 
     26 
     27 static int getTouchEventNum() //判断触摸框事件是哪一个event
     28 {
     29     char          name[64];           /* RATS: Use ok, but could be better */  
     30     char          buf[256] = { 0, };  /* RATS: Use ok */  
     31     int           fd = 0;   
     32     int           i;    
     33     for (i = 0; i < 32; i++) 
     34     {  
     35         sprintf(name, "/dev/input/event%d", i);  
     36         if ((fd = open(name, O_RDONLY, 0)) >= 0) 
     37         {  
     38             ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);   
     39             if(strstr(buf, "MTOUC Touch"))
     40             {
     41                 close(fd);
     42                 return i;
     43             }
     44             //printf("%s
    ", name);  
     45             //printf("name: %s
    ", buf);           
     46             close(fd);  
     47         }
     48     }
     49     return -1;
     50 }
     51 
     52 static void* readInput(void *data)
     53 {
     54     struct input_event inputEvent;
     55     while(1)
     56     {
     57         read(fd, &inputEvent, sizeof(struct input_event));
     58         // 向管道中写数据
     59         write(fds[1], &inputEvent, sizeof(struct input_event));
     60     }
     61     return NULL;
     62 }
     63 
     64 static void* dispatchInput(void *data) 
     65 {
     66     struct input_event inputEvent;
     67     int flag = 1;
     68     while(1)
     69     {
     70         //从管道中读取数据
     71         read(fds[0], &inputEvent, sizeof(struct input_event));
     72         
     73         if(inputEvent.type == EV_ABS && inputEvent.code == ABS_X ){
     74             float fv = inputEvent.value * 1.0;
     75             x = fv * xScale;
     76             continue;
     77         }
     78         if(inputEvent.type == EV_ABS && inputEvent.code == ABS_Y ){
     79              float fv = inputEvent.value * 1.0;
     80              y = fv * yScale;
     81              continue;
     82         }
     83         if(inputEvent.type == EV_KEY && inputEvent.code == BTN_TOUCH ){
     84             pressure = inputEvent.value;
     85             if(1 == pressure && flag)
     86             {
     87                 flag = 0;
     88             }
     89             else if(0 == pressure)
     90             {
     91                 flag  = 1;
     92             }
     93             continue;
     94         }
     95         //增加flag的判断作用是touchMajor和toushMinor事件在pressure事件之前的比较准确
     96         if(inputEvent.type == EV_ABS && inputEvent.code == ABS_MT_TOUCH_MAJOR && flag ){
     97              float fv = inputEvent.value * 1.0;
     98              touchMajor = fv ;
     99              continue;
    100         }
    101         if(inputEvent.type == EV_ABS && inputEvent.code == ABS_MT_TOUCH_MINOR && flag ){
    102             float fv = inputEvent.value * 1.0;
    103             touchMinor = fv;
    104             continue;
    105         }
    106     }
    107     return NULL;
    108 }
    109 
    110 
    111 JNIEXPORT jint JNICALL Java_android_wf_MotionEvent_initEvent(JNIEnv *env, jclass clazz)
    112 {
    113     int num = getTouchEventNum();
    114     if( num == -1)
    115     {
    116         printf("No Touch Event
    ");
    117         return -1;
    118     }
    119     char name[64];
    120     sprintf(name, "/dev/input/event%d", num);
    121     fd = open(name, O_RDWR);
    122     if(fd < 0)
    123     {
    124         //LOGI("Open dev Error");
    125         return fd;
    126     }
    127     
    128     //创建无名管道
    129     if(-1 == pipe(fds))
    130     {
    131         printf("pipe
    ");
    132         exit(-1);
    133     }
    134     
    135     pthread_t readId, disPatchId; 
    136     pthread_create(&readId, NULL, readInput, NULL);
    137     sleep(1);
    138     pthread_create(&disPatchId, NULL, dispatchInput, NULL);
    139 
    140     return fd;
    141 }
    142 
    143 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getXX(JNIEnv *env, jclass clazz)
    144 {
    145     return x;
    146 }
    147 
    148 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getYY(JNIEnv *env, jclass clazz)
    149 {
    150     return y;
    151 }
    152 
    153 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getW(JNIEnv *env, jclass clazz)
    154 {
    155     return touchMajor;
    156 }
    157 
    158 JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getH(JNIEnv *env, jclass clazz)
    159 {
    160     return touchMinor;
    161 }

    最后在来个Android的Mk文件:

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)

    arch := $(TARGET_ARCH)
    LOCAL_C_INCLUDES := $(KERNEL_HEADERS)

    LOCAL_LDLIBS += -lpthread -lrt -ldl -lm    #貌似可以不加

    LOCAL_MODULE:= libMotionEvent

    LOCAL_SRC_FILES += jni/MotionEvent.c
    include $(BUILD_SHARED_LIBRARY)

  • 相关阅读:
    leaflet antvPath示例
    mysql根据属性分组找最值
    java stream流中的collect()方法详解
    Stream使用Collector.tomap方法value值为null时报空指针异常 解决方案
    mysql自定义函数计算时间段内的工作日(支持跨年)
    经典面试题:ES如何做到亿级数据查询毫秒级返回?
    一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~
    使用Docker+nginx部署Vue项目
    linux重定向及/dev/null 2>&1详解
    Linux文件目录变只读(Read-only file system)导致mysql启动失败
  • 原文地址:https://www.cnblogs.com/winfu/p/5629873.html
Copyright © 2011-2022 走看看