Android App层通过JNI从驱动获取Input Event

1 概述

 

尝试在App层直接读取驱动的Input Event,获取触屏事件(本文获取的是电磁笔触屏事件),而不通过AndroidInput Framework.

 

 

2 架构



3 实现

3.1 JNI

共有以下几个文件:

 

3.1.1 input_pen.h

 

首先看input_pen.h

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _INPUT_PEN_H  
  2. #define _INPUT_PEN_H  
  3.    
  4.    
  5. #include <pthread.h>  
  6. #include <linux/input.h>  
  7. #include <sys/types.h>  
  8. #include <linux/types.h>  
  9.    
  10. #ifdef _cplusplus  
  11. extern "C" {  
  12. #endif  
  13.    
  14. //获取input_event数据的方法指针,由App层提供  
  15.     typedef void (*get_event_callback)(__u16 type, __u16 code, __s32 value );  
  16.    
  17. //创建线程的函数指针,通过Java虚拟机创建  
  18.     typedef pthread_t (*create_thread_callback)(const char* name, void (*start)(void *), void* arg);  
  19.    
  20. //释放线程资源的函数指针  
  21.     typedef int (*detach_thread_callback)(void);  
  22.    
  23. //回调函数结构体  
  24.     typedef struct {  
  25.         get_event_callback get_event_cb;  
  26.         create_thread_callback create_thread_cb;  
  27.         detach_thread_callback detach_thread_cb;  
  28.     } input_callback;  
  29.    
  30.     /*******************************************************************/  
  31. //public methods  
  32.    
  33. //初始化函数  
  34.     unsigned char input_pen_init(input_callback *callback);  
  35.    
  36. //退出函数  
  37.     void input_pen_exit();  
  38.    
  39.    
  40. /*******************************************************************/  
  41.    
  42.    
  43. #ifdef _cplusplus  
  44. }  
  45. #endif  
  46.    
  47. #endif  
  48.    
  49.    

 

3.1.2 input_pen.cpp

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <pthread.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <unistd.h>  
  7. #include <fcntl.h>  
  8. #include <sys/types.h>  
  9. #include <sys/epoll.h>  
  10. #include <sys/wait.h>  
  11. #include <sys/un.h>  
  12. #include <stddef.h>  
  13. #include <linux/input.h>  
  14.    
  15. #include "input_pen.h"  
  16. #include "debug.h"  
  17.    
  18.    
  19.    
  20. //驱动路径  
  21. #define DEV_PATH "/dev/input/event1"  
  22.    
  23. //最大侦听  
  24. #define MAX_EVENTS 1  
  25.    
  26. //epoll_wait的最大时间  
  27. #define EPOLL_SLEEP 200  
  28.    
  29. //线程是否由pthread创建,否则由JVM创建  
  30. #define USING_PTHREAD 0  
  31.    
  32.    
  33. #if USING_PTHREAD  
  34. #define LOGD(fmt, arg...) do{printf(fmt"\n", ##arg);}while(0)  
  35. #define LOGE LOGD  
  36. #endif  
  37.    
  38. /**************************************************************************************/  
  39.    
  40. //static variable  
  41.    
  42. //当前驱动文件指针  
  43. static int fd = 0;  
  44. //epoll文件指针  
  45. static int epoll_fd = 0;  
  46. //epoll_event数组  
  47. static struct epoll_event events[MAX_EVENTS];  
  48. //回调函数  
  49. static input_callback *callbacks = NULL;  
  50.    
  51. //标记线程是否已启动  
  52. static unsigned char start_flag = 0;  
  53. //标记线程是否已退出  
  54. static unsigned char exit_flag = 0;  
  55. //线程锁  
  56. static pthread_mutex_t exit_mutex;  
  57.    
  58. /**************************************************************************************/  
  59.    
  60.    
  61. //set non-blocking for fd  
  62. static int set_non_blocking(int fd) {  
  63.     int opts;  
  64.    
  65.     opts = fcntl(fd, F_GETFL);  
  66.     if (opts < 0) {  
  67.         LOGE("fcntl F_GETFL error: %s", strerror(errno));  
  68.         return -1;  
  69.     }  
  70.     opts = (opts | O_NONBLOCK);  
  71.     if (fcntl(fd, F_SETFL, opts) < 0) {  
  72.         LOGE("fcntl F_SETFL error: %s", strerror(errno));  
  73.         return -1;  
  74.     }  
  75.    
  76.     return 0;  
  77. }  
  78.    
  79. //register epoll events for fd  
  80. static void epoll_register( int  epoll_fd, int  fd ) {  
  81.     struct epoll_event  ev;  
  82.     int         ret;  
  83.    
  84.     ev.events  = EPOLLIN;//interested in receiving data  
  85.     ev.data.fd = fd;  
  86.    
  87.     do {  
  88.         //register events for fd  
  89.         ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );  
  90.     } while (ret < 0 && errno == EINTR);  
  91.    
  92. }  
  93.    
  94.    
  95.    
  96. //remove epoll events for fd  
  97. static void epoll_unregister( int  epoll_fd, int  fd ) {  
  98.     int  ret;  
  99.     do {  
  100.         ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );  
  101.     } while (ret < 0 && errno == EINTR);  
  102.    
  103. }  
  104.    
  105.    
  106. //通知退出线程,由其他线程调用  
  107. static void thread_cancel() {  
  108.     LOGD("thread_cancel");  
  109.     pthread_mutex_lock(&exit_mutex);  
  110.    
  111.     exit_flag = 1;  
  112.    
  113.     pthread_mutex_unlock(&exit_mutex);  
  114. }  
  115.    
  116. //停止线程,由本线程调用  
  117. static void thread_exit() {  
  118.     unsigned char flag ;  
  119.    
  120.    
  121.     pthread_mutex_lock(&exit_mutex);  
  122.    
  123.     flag = exit_flag;  
  124.    
  125.     pthread_mutex_unlock(&exit_mutex);  
  126.    
  127.     if (flag == 1) {  
  128.         LOGD("thread_exit");  
  129.         //close devices  
  130.         close(fd);  
  131.    
  132.         //clean variablies  
  133.         fd = 0;  
  134.         epoll_fd = 0;  
  135.         start_flag = 0;  
  136.         exit_flag = 0;  
  137.         //release thread resources  
  138.         if (callbacks != NULL && callbacks->detach_thread_cb != NULL) {  
  139.             callbacks->detach_thread_cb();  
  140.             LOGD("callbacks->detach_thread_cb();\n");  
  141.         }  
  142.    
  143.         //exit current thread  
  144.         pthread_exit(NULL);  
  145.    
  146.    
  147.     }  
  148. }  
  149.    
  150.    
  151. //线程运行函数  
  152. #if USING_PTHREAD  
  153. static void *run(void *args) {  
  154. #else  
  155. static void run(void *args) {  
  156.    
  157. #endif  
  158.     int n = 0;  
  159.     int i = 0;  
  160.     int res;  
  161.     struct input_event event;  
  162.    
  163.     LOGD("run...");  
  164.     while (1) {  
  165.    
  166.         thread_exit();//每次检测是否要退出运行  
  167.    
  168.    
  169.         n = epoll_wait(epoll_fd, events, MAX_EVENTS, EPOLL_SLEEP);//检测是否有事件发生  
  170.         if (n == -1) {  
  171.             LOGE("epoll_wait error:%s", strerror(errno));  
  172.             continue;  
  173.         }  
  174.    
  175.         for (i = 0; i < n; i++) {  
  176.             if (events[i].data.fd == fd) { //有读事件发生  
  177.                 res = read(fd, &event, sizeof(event));  
  178.                 if (res < (int)sizeof(event)) {  
  179.                     LOGE("could not get event\n");  
  180.                     continue;  
  181.                 }  
  182.    
  183. #if (!USING_PTHREAD)  
  184.                 //把input_event的数据回调到java层  
  185.                 if (callbacks != NULL && callbacks->get_event_cb != NULL) {  
  186.                     callbacks->get_event_cb(event.type, event.code, event.value);  
  187.                 }  
  188. #else  
  189.                 //printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec);  
  190.                 if (event.type == EV_ABS) {  
  191.                     printf("%04x %04x %08x\n", event.type, event.code, event.value);  
  192.                 }  
  193. #endif  
  194.             }  
  195.         }  
  196.     }  
  197. #if USING_PTHREAD  
  198.     return NULL;  
  199. #else  
  200.     return ;  
  201. #endif  
  202.    
  203. }  
  204.    
  205.    
  206. //初始化函数  
  207. unsigned char input_pen_init(input_callback *cb) {  
  208.    
  209.     pthread_t thread;  
  210.    
  211.     LOGD("input_pen_init");  
  212.     if (start_flag) {  
  213.         return 1;  
  214.     }  
  215.    
  216.     //callbacks  
  217.     callbacks = cb;  
  218.    
  219.     //open device  
  220.     fd = open(DEV_PATH, O_RDWR);  
  221.     if (fd < 0) {  
  222.         LOGE("open device failed!\n");  
  223.         return 0;  
  224.     }  
  225.    
  226.     //create epoll  
  227.     epoll_fd = epoll_create(MAX_EVENTS);  
  228.     if (epoll_fd == -1) {  
  229.         LOGE("epoll_create failed!\n");  
  230.         return 0;  
  231.     }  
  232.     //set non-blocking  
  233.     set_non_blocking(fd);  
  234.    
  235.     //epoll register  
  236.     epoll_register(epoll_fd, fd);  
  237.    
  238.     //mutex  
  239.     if (pthread_mutex_init(&exit_mutex, NULL) != 0) {  
  240.         LOGE("pthread_mutex_initn failed!");  
  241.         return 0;  
  242.     }  
  243.    
  244.     //create thread  
  245. #if USING_PTHREAD  
  246.     if (pthread_create(&thread, NULL, run, (void *)NULL) != 0) {  
  247.         LOGE("pthread_create failed!\n");  
  248.         return 0;  
  249.     }  
  250. #else  
  251.     if (callbacks != NULL && callbacks->create_thread_cb != NULL) {  
  252.         thread = callbacks->create_thread_cb("input_pen_thread", run, NULL);  
  253.         if (thread == 0) {  
  254.             LOGE("create thread failed!\n");  
  255.             return 0;  
  256.         }  
  257.    
  258.         start_flag = 1;  
  259.         LOGD("input_pen_init success!");  
  260.         return 1;  
  261.    
  262.     }  
  263. #endif  
  264.    
  265.    
  266.    
  267.     return 0;  
  268.    
  269. }  
  270.    
  271. //退出函数  
  272. void input_pen_exit() {  
  273.     thread_cancel();  
  274. }  
  275.    
  276. #if USING_PTHREAD  
  277. int main() {  
  278.     int count = 0;  
  279.     input_pen_init(NULL);  
  280.    
  281.     while (1) {  
  282.         sleep(1);  
  283.         count ++;  
  284.         if (count == 20) {  
  285.             thread_cancel();  
  286.             sleep(1);  
  287.             break;  
  288.         }  
  289.     }  
  290.     return 0;  
  291. }  
  292. #endif  
  293.    
  294.    
  295.    
  296.    

以上的关键流程为:

 

1、open驱动文件,初始化epoll,创建线程。

2、在线程中通过epoll_wait检测事件,有事件发生则通过read函数读取驱动的input_event数据,并通过get_event_cb回调到Jav层。

 

3.1.3 com_jiagutech_input_InputPen.cpp

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdlib.h>  
  2. #include <malloc.h>  
  3. #include <jni.h>  
  4. #include <JNIHelp.h>  
  5. #include <utils/Log.h>  
  6. #include "android_runtime/AndroidRuntime.h"  
  7.    
  8. #include "input_pen.h"  
  9. #include "debug.h"  
  10.    
  11. //Java类名  
  12. #define CLASS_NAME "com/jiagutech/input/InputPen"  
  13.    
  14. using namespace android;  
  15.    
  16.    
  17. static jobject mCallbacksObj = NULL;  
  18. static jmethodID method_get_event;  
  19.    
  20.    
  21. static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {  
  22.     if (env->ExceptionCheck()) {  
  23.         LOGE("An exception was thrown by callback '%s'.", methodName);  
  24.         LOGE_EX(env);  
  25.         env->ExceptionClear();  
  26.     }  
  27. }  
  28.    
  29. //获得input_event数据的回调函数  
  30. static void GetEventCallback(__u16 type, __u16 code, __s32 value) {  
  31.     JNIEnv* env = AndroidRuntime::getJNIEnv();  
  32.     //invoke java callback method  
  33.     env->CallVoidMethod(mCallbacksObj, method_get_event, type, code, value);  
  34.    
  35.     checkAndClearExceptionFromCallback(env, __FUNCTION__);  
  36. }  
  37.    
  38. //创建线程的回调函数  
  39. static pthread_t CreateThreadCallback(const char* name, void (*start)(void *), void* arg) {  
  40.     return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);  
  41. }  
  42.    
  43. //释放线程资源的回调函数  
  44. static int DetachThreadCallback(void) {  
  45.     JavaVM* vm;  
  46.     jint result;  
  47.    
  48.     vm = AndroidRuntime::getJavaVM();  
  49.     if (vm == NULL) {  
  50.         LOGE("detach_thread_callback :getJavaVM failed\n");  
  51.         return -1;  
  52.     }  
  53.    
  54.     result = vm->DetachCurrentThread();  
  55.     if (result != JNI_OK)  
  56.         LOGE("ERROR: thread detach failed\n");  
  57.     return result;  
  58. }  
  59.    
  60.    
  61. //回调函数结构体变量  
  62. static input_callback mCallbacks = {  
  63.     GetEventCallback,  
  64.     CreateThreadCallback,  
  65.     DetachThreadCallback,  
  66. };  
  67.    
  68. //初始化Java的回调函数  
  69. static void jni_class_init_native  
  70. (JNIEnv* env, jclass clazz) {  
  71.     LOGD("jni_class_init_native");  
  72.    
  73.     method_get_event = env->GetMethodID(clazz, "getEvent""(III)V");  
  74.    
  75.    
  76. }  
  77.    
  78. //初始化  
  79. static jboolean jni_input_pen_init  
  80. (JNIEnv *env, jobject obj) {  
  81.     LOGD("jni_input_pen_init");  
  82.    
  83.     if (!mCallbacksObj)  
  84.         mCallbacksObj = env->NewGlobalRef(obj);  
  85.    
  86.     return  input_pen_init(&mCallbacks);  
  87. }  
  88.    
  89.    
  90. //退出  
  91. static void jni_input_pen_exit  
  92. (JNIEnv *env, jobject obj) {  
  93.     LOGD("jni_input_pen_exit");  
  94.     input_pen_exit();  
  95. }  
  96.    
  97. static const JNINativeMethod gMethods[] = {  
  98.     { "class_init_native","()V", (void *)jni_class_init_native },  
  99.     { "native_input_pen_init","()Z", (void *)jni_input_pen_init },  
  100.     { "native_input_pen_exit","()V", (void *)jni_input_pen_exit },  
  101. };  
  102.    
  103.    
  104.    
  105. static int registerMethods(JNIEnv* env) {  
  106.    
  107.    
  108.     const charconst kClassName = CLASS_NAME;  
  109.     jclass clazz;  
  110.     /* look up the class */  
  111.     clazz = env->FindClass(kClassName);  
  112.     if (clazz == NULL) {  
  113.         LOGE("Can't find class %s/n", kClassName);  
  114.         return -1;  
  115.     }  
  116.     /* register all the methods */  
  117.     if (env->RegisterNatives(clazz,gMethods,sizeof(gMethods)/sizeof(gMethods[0])) != JNI_OK) {  
  118.         LOGE("Failed registering methods for %s/n", kClassName);  
  119.         return -1;  
  120.     }  
  121.     /* fill out the rest of the ID cache */  
  122.     return 0;  
  123. }  
  124.    
  125.    
  126. jint JNI_OnLoad(JavaVM* vm, void* reserved) {  
  127.     JNIEnv* env = NULL;  
  128.     jint result = -1;  
  129.     LOGI("InputPen JNI_OnLoad");  
  130.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  131.         LOGE("ERROR: GetEnv failed/n");  
  132.         goto fail;  
  133.     }  
  134.    
  135.     if (env == NULL) {  
  136.         goto fail;  
  137.     }  
  138.     if (registerMethods(env) != 0) {  
  139.         LOGE("ERROR: PlatformLibrary native registration failed/n");  
  140.         goto fail;  
  141.     }  
  142.     /* success -- return valid version number */  
  143.     result = JNI_VERSION_1_4;  
  144. fail:  
  145.     return result;  
  146. }  
  147.    
  148.    
  149.    


3.1.4 Android.mk

[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_SRC_FILES:= \  
  5.     input_pen.cpp \  
  6.     com_jiagutech_input_InputPen.cpp  
  7.       
  8. LOCAL_MODULE_TAGS := optional  
  9.   
  10. LOCAL_SHARED_LIBRARIES := liblog libcutils libandroid_runtime libnativehelper  
  11. LOCAL_PRELINK_MODULE := false  
  12.   
  13. LOCAL_MODULE:= libinput_pen  
  14. include $(BUILD_SHARED_LIBRARY)  
  15.   
  16.   
  17. #LOCAL_MODULE:=inputpen  
  18. #include $(BUILD_EXECUTABLE)   


1.1.1 Debug.h

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _DEBUG_H  
  2. #define _DEBUG_H  
  3.    
  4. #include <utils/Log.h>  
  5.    
  6. #ifdef ALOGD  
  7. #define LOGD      ALOGD  
  8. #endif  
  9. #ifdef ALOGV  
  10. #define LOGV      ALOGV  
  11. #endif  
  12. #ifdef ALOGE  
  13. #define LOGE      ALOGE  
  14. #endif  
  15. #ifdef ALOGI  
  16. #define LOGI      ALOGI  
  17. #endif  
  18.    
  19. #define LOG_TAG "InputPen"  
  20.    
  21. #endif   
  22.    
  23.    



3.2 App

共有两个文件:

PenEvent.java

InputPen.java

 

3.2.1 PenEvent.java

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.jiagutech.input;  
  2.    
  3. public class PenEvent {  
  4.    
  5.    
  6.     public PenEvent() {  
  7.    
  8.     }  
  9.    
  10.     public final static int ACTION_DOWN = 0x0;  
  11.     public final static int ACTION_UP = 0x1;  
  12.     public final static int ACTION_MOVE = 0x2;  
  13.    
  14.     //表示事件类型,down/up/move  
  15.     private int action;  
  16.     //x轴坐标  
  17.     private float x;  
  18.     //y轴坐标  
  19.     private float y;  
  20.     //压力数据  
  21.     private float pressure;  
  22.    
  23.     public void setAction(int action) {  
  24.         this.action = action;  
  25.     }  
  26.    
  27.     public int getAction() {  
  28.         return action;  
  29.     }  
  30.    
  31.    
  32.     public void setX(float x) {  
  33.         this.x = x;  
  34.     }  
  35.    
  36.     public float getX() {  
  37.         return x;  
  38.     }  
  39.    
  40.    
  41.     public void setY(float y) {  
  42.         this.y = y;  
  43.     }  
  44.    
  45.     public float getY() {  
  46.         return y;  
  47.     }  
  48.    
  49.     public void setPressure(float p) {  
  50.         this.pressure = p;  
  51.     }  
  52.    
  53.     public float getPressure() {  
  54.         return pressure;  
  55.     }  
  56.    
  57.    
  58.    
  59. }  
  60.    
  61.    

3.2.2 InputPen.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.jiagutech.input;  
  2.    
  3. import java.util.LinkedList;  
  4.    
  5. import android.os.Handler;  
  6.    
  7.    
  8. public class InputPen {  
  9.    
  10.     /**********************************************************************************/  
  11.     private static InputPen instance = null;  
  12.    
  13.     private boolean mStarted = false;  
  14.    
  15.     private final static String TAG = "InputPen";  
  16.    
  17.     //主线程Handler  
  18.     private Handler mHandler = null;  
  19.     //PenEvent列表  
  20.     private LinkedList<PenEvent> mEventList = new LinkedList<PenEvent>();  
  21.     //锁  
  22.     private Object mListLock = new Object();  
  23.    
  24.     /*******************************************************************/  
  25.     //以下定义请参考input_event.h文件  
  26.     private final static int EV_SYN = 0x0;  
  27.     private final static int EV_KEY = 0x01;  
  28.    
  29.     private final static int EV_ABS = 0x03;  
  30.    
  31.    
  32.     private final static int  ABS_X = 0x00;  
  33.     private final static int  ABS_Y = 0x01;  
  34.     private final static int  ABS_PRESSURE = 0x18;  
  35.     private final static int  BTN_TOUCH = 0x14a;  
  36.     private final static int  BTN_TOOL_PEN = 0x140;  
  37.     private final static int  BTN_STYLUS = 0x14b;  
  38.     /*******************************************************************/  
  39.     //原始的x最大分辨率  
  40.     private static final float MAX_X = 15360.0f;  
  41.     //屏幕x最大分辨率  
  42.     private static final float MAX_X_STANDARD = 1280.0f;  
  43.    
  44.     //原始的y最大分辨率  
  45.     private static final float MAX_Y = 9600.0f;  
  46.     //屏幕y最大分辨率  
  47.     private static final float MAX_Y_STANDARD = 800.0f;  
  48.    
  49.     //原始的最大压力数据  
  50.     private static final float MAX_PRESSURE = 1023.0f;  
  51.     //Android标准最大压力数据  
  52.     private static final float MAX_PRESSURE_STANDARD= 1.0f;  
  53.    
  54.     private int _x=-1,_y=-1,_pressure=-1;  
  55.     private int _bintouch = 0, _lastBinTouch = 0;  
  56.     //x轴转换系数  
  57.     private float xScale = MAX_X_STANDARD / MAX_X;  
  58.     //y轴转换系数  
  59.     private float yScale = MAX_Y_STANDARD / MAX_Y;  
  60.     //压力值转换系统  
  61.     private float pScale = MAX_PRESSURE_STANDARD / MAX_PRESSURE;  
  62.    
  63.     //y轴便宜  
  64.     private float yOffset = 73.0f;  
  65.    
  66.     /** 
  67.      * 加载libinput_pen.so,并初始化回调函数 
  68.      */  
  69.     static {  
  70.         try {  
  71.             System.loadLibrary("input_pen");  
  72.             class_init_native();  
  73.    
  74.    
  75.         } catch (UnsatisfiedLinkError e) {  
  76.             e.printStackTrace();  
  77.         }  
  78.    
  79.     }  
  80.    
  81.     private InputPen() {  
  82.     }  
  83.    
  84.     /** 
  85.      * 单例模式 
  86.      * @return 
  87.      */  
  88.     public static synchronized InputPen getInstance() {  
  89.         if (instance == null) {  
  90.             instance = new InputPen();  
  91.         }  
  92.         return instance;  
  93.     }  
  94.    
  95.     /** 
  96.      * 通知主线程获取PenEvent进行处理 
  97.      * 
  98.      */  
  99.     private void onPenTouch() {  
  100.         if (mHandler != null) {  
  101.             mHandler.sendEmptyMessage(0);  
  102.         }  
  103.    
  104.     }  
  105.    
  106.     /** 
  107.      * 设置主线程handler 
  108.      * @param handler 
  109.      */  
  110.     public void setHandler(Handler handler) {  
  111.         mHandler = handler;  
  112.     }  
  113.    
  114.     /** 
  115.      * 添加PenEvent到list 
  116.      * @param event 
  117.      */  
  118.     private void addPenEvent(PenEvent event) {  
  119.         synchronized (mListLock) {  
  120.             mEventList.add(event);  
  121.         }  
  122.     }  
  123.    
  124.     /** 
  125.      * 从list获取最旧的PenEvent 
  126.      * @return 
  127.      */  
  128.     public PenEvent getPenEvent() {  
  129.         PenEvent event = null;  
  130.         synchronized (mListLock) {  
  131.             if (mEventList.size() > 0) {  
  132.                 event = mEventList.removeFirst();  
  133.             }  
  134.         }  
  135.    
  136.         return event;  
  137.     }  
  138.    
  139.    
  140.     /*******************************************************************/  
  141.     //public method  
  142.    
  143.     /** 
  144.      * 坐标转换,并生成PenEvent数据 
  145.      * @param event 
  146.      */  
  147.     protected void transform(PenEvent event) {  
  148.         float x = MAX_Y_STANDARD - ((float)_y) * yScale;  
  149.         float y = (float)_x * xScale - yOffset;  
  150.         float p = (float)_pressure * pScale;  
  151.         event.setX(x);  
  152.         event.setY(y);  
  153.         event.setPressure(p);  
  154.     }  
  155.    
  156.     /** 
  157.      * 处理input_event数据 
  158.      */  
  159.     protected void processEvent() {  
  160.    
  161.         if (_bintouch != _lastBinTouch ) {  
  162.             _lastBinTouch = _bintouch;  
  163.             //Log.d(TAG, String.format("x=%d,y=%d,pressure=%d,bintouch=%d", _x,_y,_pressure,_bintouch));  
  164.             if (_bintouch == 1) { //down事件  
  165.                 PenEvent event = new PenEvent();  
  166.                 event.setAction(PenEvent.ACTION_DOWN);  
  167.                 transform(event);  
  168.                 addPenEvent(event);  
  169.                 onPenTouch();  
  170.    
  171.             } else { //up事件  
  172.                 PenEvent event = new PenEvent();  
  173.                 event.setAction(PenEvent.ACTION_UP);  
  174.                 transform(event);  
  175.                 addPenEvent(event);  
  176.                 onPenTouch();  
  177.             }  
  178.         } else if (_bintouch == 1) { //move事件  
  179.             PenEvent event = new PenEvent();  
  180.             event.setAction(PenEvent.ACTION_MOVE);  
  181.             transform(event);  
  182.             addPenEvent(event);  
  183.             onPenTouch();  
  184.    
  185.         }  
  186.    
  187.    
  188.    
  189.    
  190.     }  
  191.    
  192.     /** 
  193.      * 获取input_event数据,由jni层调用此函数 
  194.      * @param type 
  195.      * @param code 
  196.      * @param value 
  197.      */  
  198.     protected void getEvent(int type, int code, int value) {  
  199.         switch (type) {  
  200.    
  201.         case EV_SYN:  
  202.             processEvent();  
  203.             break;  
  204.    
  205.         case EV_KEY:  
  206.             if (code == BTN_TOUCH) {  
  207.                 _bintouch = value;  
  208.             }  
  209.             break;  
  210.         case EV_ABS:  
  211.             if (code == ABS_X) {  
  212.                 _x = value;  
  213.             } else if (code == ABS_Y) {  
  214.                 _y = value;  
  215.             } else if (code == ABS_PRESSURE) {  
  216.                 _pressure = value;  
  217.             }  
  218.             break;  
  219.         default:  
  220.             break;  
  221.         }  
  222.     }  
  223.    
  224.     /** 
  225.      * 启动线程 
  226.      */  
  227.     protected void start() {  
  228.         if (!mStarted) {  
  229.             if (native_input_pen_init()) {  
  230.                 mStarted = true;  
  231.             }  
  232.    
  233.         }  
  234.    
  235.    
  236.     }  
  237.    
  238.     /** 
  239.      * 停止线程 
  240.      */  
  241.     protected void stop() {  
  242.         if (mStarted) {  
  243.             native_input_pen_exit();  
  244.             mStarted = false;  
  245.         }  
  246.    
  247.     }  
  248.    
  249.     public void dispose() {  
  250.         stop();  
  251.     }  
  252.    
  253.     @Override  
  254.     protected void finalize() throws Throwable {  
  255.    
  256.         stop();  
  257.         // TODO Auto-generated method stub  
  258.         super.finalize();  
  259.     }  
  260.    
  261.    
  262.     /*******************************************************************/  
  263.     //native method  
  264.     protected  static native void class_init_native();  
  265.    
  266.     protected  native boolean native_input_pen_init();  
  267.    
  268.     protected  native void native_input_pen_exit();  
  269. }  
  270.    
  271.    
  272.    


3.2.3 Activity

Activity可以通过调用InputPenstart函数,启动读取线程,再调用setHandler设置Handler,从而就可在Handler中处理PenEvent数据了。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值