首先说下思路,本文采用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上层封装代码

 package android.wf;
public final class MotionEvent { public MotionEvent(){
int fd = initEvent();
System.out.println("fd = %d\n");
} public final float getX() {
return getXX();
} public final float getY() {
return getYY();
} public final float getWidth() {
return getH();
} public final float getHight() {
return getW();
} static
{
System.loadLibrary("MotionEvent");
} private static native float getW();
private static native float getH();
private static native int initEvent();
private static native float getXX();
private static native float getYY(); }

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

 /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class android_wf_MotionEvent */ #ifndef _Included_android_wf_MotionEvent
#define _Included_android_wf_MotionEvent
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: android_wf_MotionEvent
* Method: initEvent
* Signature: ()F
*/
JNIEXPORT jint JNICALL Java_android_wf_MotionEvent_initEvent
(JNIEnv *, jclass); /*
* Class: android_wf_MotionEvent
* Method: getXX
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getXX
(JNIEnv *, jclass); /*
* Class: android_wf_MotionEvent
* Method: getYY
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getYY
(JNIEnv *, jclass);
JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getW
(JNIEnv *, jclass);
JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getH
(JNIEnv *, jclass );
#ifdef __cplusplus
}
#endif
#endif

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

 #include <linux/input.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <jni.h>
#include "android_wf_MotionEvent.h"
#include<android/log.h> //LCD和触摸框转换比例
float xScale = 1920.0/;
float yScale = 1080.0/; int fd ; // dev的文件描述符
int fds[]; //管道 jfloat x;
jfloat y;
jfloat pressure;
jfloat touchMajor;
jfloat touchMinor; static int getTouchEventNum() //判断触摸框事件是哪一个event
{
char name[]; /* RATS: Use ok, but could be better */
char buf[] = { , }; /* RATS: Use ok */
int fd = ;
int i;
for (i = ; i < ; i++)
{
sprintf(name, "/dev/input/event%d", i);
if ((fd = open(name, O_RDONLY, )) >= )
{
ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
if(strstr(buf, "MTOUC Touch"))
{
close(fd);
return i;
}
//printf("%s\n", name);
//printf("name: %s\n", buf);
close(fd);
}
}
return -;
} static void* readInput(void *data)
{
struct input_event inputEvent;
while()
{
read(fd, &inputEvent, sizeof(struct input_event));
// 向管道中写数据
write(fds[], &inputEvent, sizeof(struct input_event));
}
return NULL;
} static void* dispatchInput(void *data)
{
struct input_event inputEvent;
int flag = ;
while()
{
//从管道中读取数据
read(fds[], &inputEvent, sizeof(struct input_event)); if(inputEvent.type == EV_ABS && inputEvent.code == ABS_X ){
float fv = inputEvent.value * 1.0;
x = fv * xScale;
continue;
}
if(inputEvent.type == EV_ABS && inputEvent.code == ABS_Y ){
float fv = inputEvent.value * 1.0;
y = fv * yScale;
continue;
}
if(inputEvent.type == EV_KEY && inputEvent.code == BTN_TOUCH ){
pressure = inputEvent.value;
if( == pressure && flag)
{
flag = ;
}
else if( == pressure)
{
flag = ;
}
continue;
}
//增加flag的判断作用是touchMajor和toushMinor事件在pressure事件之前的比较准确
if(inputEvent.type == EV_ABS && inputEvent.code == ABS_MT_TOUCH_MAJOR && flag ){
float fv = inputEvent.value * 1.0;
touchMajor = fv ;
continue;
}
if(inputEvent.type == EV_ABS && inputEvent.code == ABS_MT_TOUCH_MINOR && flag ){
float fv = inputEvent.value * 1.0;
touchMinor = fv;
continue;
}
}
return NULL;
} JNIEXPORT jint JNICALL Java_android_wf_MotionEvent_initEvent(JNIEnv *env, jclass clazz)
{
int num = getTouchEventNum();
if( num == -)
{
printf("No Touch Event\n");
return -;
}
char name[];
sprintf(name, "/dev/input/event%d", num);
fd = open(name, O_RDWR);
if(fd < )
{
//LOGI("Open dev Error");
return fd;
} //创建无名管道
if(- == pipe(fds))
{
printf("pipe\n");
exit(-);
} pthread_t readId, disPatchId;
pthread_create(&readId, NULL, readInput, NULL);
sleep();
pthread_create(&disPatchId, NULL, dispatchInput, NULL); return fd;
} JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getXX(JNIEnv *env, jclass clazz)
{
return x;
} JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getYY(JNIEnv *env, jclass clazz)
{
return y;
} JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getW(JNIEnv *env, jclass clazz)
{
return touchMajor;
} JNIEXPORT jfloat JNICALL Java_android_wf_MotionEvent_getH(JNIEnv *env, jclass clazz)
{
return touchMinor;
}

最后在来个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)

使用JNI封装底层input系统提供的event事件的更多相关文章

  1. Android 4.0 事件输入(Event Input)系统

    参考:http://blog.csdn.net/myarrow/article/details/7091061 1. TouchScreen功能在Android4.0下不工作 原来在Android2. ...

  2. Linux input系统数据上报流程【转】

    转自:https://segmentfault.com/a/1190000017255939 作为鸡生蛋系列文章,这里主要关注Linux input系统,主要为触摸事件上报流程. 读该文章最好有对li ...

  3. 选择排序法、冒泡排序法、插入排序法、系统提供的底层sort方法排序之毫秒级比较

    我的代码: package PlaneGame;/** * 选择排序法.冒泡排序法.插入排序法.系统提供的底层sort方法排序之毫秒级比较 * @author Administrator */impo ...

  4. UIView封装动画--iOS利用系统提供方法来做转场动画

    UIView封装动画--iOS利用系统提供方法来做转场动画 UIViewAnimationOptions option; if (isNext) { option=UIViewAnimationOpt ...

  5. UIView封装动画--iOS利用系统提供方法来做关键帧动画

    iOS利用系统提供方法来做关键帧动画 ios7以后才有用. /*关键帧动画 options:UIViewKeyframeAnimationOptions类型 */ [UIView animateKey ...

  6. UIView封装动画--iOS 利用系统提供方法来做弹性运动

    iOS 利用系统提供方法来做弹性运动 /*创建弹性动画 damping:阻尼,范围0-1,阻尼越接近于0,弹性效果越明显 velocity:弹性复位的速度 */ [UIView animateWith ...

  7. Linux 下Input系统应用编程实战

    作者:杨源鑫(也是我们的校园代理) 经授权转载于公众号嵌入式开发圈,有些许修改. 什么是input子系统?不管是什么操作系统,都有一个程序用于管理各种输入设备,哪些是输入设备?比如,电脑键盘.鼠标,智 ...

  8. iOS系统提供开发环境下命令行编译工具:xcodebuild

    iOS系统提供开发环境下命令行编译工具:xcodebuild[3] xcodebuild 在介绍xcodebuild之前,需要先弄清楚一些在XCode环境下的一些概念[4]: Workspace:简单 ...

  9. IP编辑控件(因为封装的是系统自带控件,所以也使用了CreateSubClass,不过为啥要封装CN_COMMAND和CN_NOTIFY不是很明白)

    最近需要用一个IP输入控件,网上找了几个,都不符合效果,有些还有一些奇怪的Bug.后来发现原来系统已经提供了IP地址编辑控件,只是系统提供的控件不能设置只读效果.网上找了下资料,封装了一下,自己迂回一 ...

随机推荐

  1. 深入理解javascript原型和闭包系列

    从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...

  2. mybatis入门基础(四)----输入映射和输出映射

    一:输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型. 1.1.传递pojo的包装对象 1.1.1.需求描述 完成用户信息的综合查询, ...

  3. 你不知道的HttpHandler相关知识

    一.关于IHttpHandler.IsReusable 很多人不明白,这哥们到底干嘛的,估计是微软最初的一个想法--让一个对象可以一直不断地被重复使用 ,但这个想法不成熟,会带来很多隐藏问题,一个对象 ...

  4. Quartz.net 开源job调度框架(一)

    Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调度作业.它实现了作业和 ...

  5. 《C#并发编程经典实例》笔记

    1.前言 2.开宗明义 3.开发原则和要点 (1)并发编程概述 (2)异步编程基础 (3)并行开发的基础 (4)测试技巧 (5)集合 (6)函数式OOP (7)同步 1.前言 最近趁着项目的一段平稳期 ...

  6. Js apply方法详解

    我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家 ...

  7. SignalR入门之Hub

    在持久性连接的基础上,SignalR提供了一个更高层次的抽象层:Hub,基于javascript的灵活性和C#的动态特性,Hub是一个至关重要的开发模式,它消弭了客户端和服务端这两个独立的物理环境之间 ...

  8. javascript中的两个定时函数setTimeOut()和setInterVal()的区别

    js中经常性要用到间隔几秒或暂停几秒执行某个函数, 简单介绍我从网上收集到setTimeOut()和setInterVal()的区别1.setInterVal()介绍 1)定义 setInterval ...

  9. xp IP安全策略 ipseccmd

    ///下载 ipseccmd.exe //禁止 xp 连接 public static void BannedXPRunCmd() { string str = Console.ReadLine(); ...

  10. Thinking in Java——笔记(20)

    Annotations They provide information that you need to fully describe your program, but that cannot b ...