使用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上层封装代码
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事件的更多相关文章
- Android 4.0 事件输入(Event Input)系统
参考:http://blog.csdn.net/myarrow/article/details/7091061 1. TouchScreen功能在Android4.0下不工作 原来在Android2. ...
- Linux input系统数据上报流程【转】
转自:https://segmentfault.com/a/1190000017255939 作为鸡生蛋系列文章,这里主要关注Linux input系统,主要为触摸事件上报流程. 读该文章最好有对li ...
- 选择排序法、冒泡排序法、插入排序法、系统提供的底层sort方法排序之毫秒级比较
我的代码: package PlaneGame;/** * 选择排序法.冒泡排序法.插入排序法.系统提供的底层sort方法排序之毫秒级比较 * @author Administrator */impo ...
- UIView封装动画--iOS利用系统提供方法来做转场动画
UIView封装动画--iOS利用系统提供方法来做转场动画 UIViewAnimationOptions option; if (isNext) { option=UIViewAnimationOpt ...
- UIView封装动画--iOS利用系统提供方法来做关键帧动画
iOS利用系统提供方法来做关键帧动画 ios7以后才有用. /*关键帧动画 options:UIViewKeyframeAnimationOptions类型 */ [UIView animateKey ...
- UIView封装动画--iOS 利用系统提供方法来做弹性运动
iOS 利用系统提供方法来做弹性运动 /*创建弹性动画 damping:阻尼,范围0-1,阻尼越接近于0,弹性效果越明显 velocity:弹性复位的速度 */ [UIView animateWith ...
- Linux 下Input系统应用编程实战
作者:杨源鑫(也是我们的校园代理) 经授权转载于公众号嵌入式开发圈,有些许修改. 什么是input子系统?不管是什么操作系统,都有一个程序用于管理各种输入设备,哪些是输入设备?比如,电脑键盘.鼠标,智 ...
- iOS系统提供开发环境下命令行编译工具:xcodebuild
iOS系统提供开发环境下命令行编译工具:xcodebuild[3] xcodebuild 在介绍xcodebuild之前,需要先弄清楚一些在XCode环境下的一些概念[4]: Workspace:简单 ...
- IP编辑控件(因为封装的是系统自带控件,所以也使用了CreateSubClass,不过为啥要封装CN_COMMAND和CN_NOTIFY不是很明白)
最近需要用一个IP输入控件,网上找了几个,都不符合效果,有些还有一些奇怪的Bug.后来发现原来系统已经提供了IP地址编辑控件,只是系统提供的控件不能设置只读效果.网上找了下资料,封装了一下,自己迂回一 ...
随机推荐
- jquery兼容实验
使用jquery时候,曾经遇到两个问题: 1.一个页面里,使用了很多基于jquery的前端ui库,但是各个库之间对jquery的依赖的版本不一样,有的依赖jquery1.4,jquery2.0用不了: ...
- C++ this指针的用法
this指针的含义及其用法: 1. this指针是一个隐含于每一个成员函数中的特殊指针.它指向正在被该成员函数操作的那个对象.2. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针, ...
- [Asp.net 5] Localization-简单易用的本地化
本地化也叫国际化,就是做多语言程序时,可以一键式将当前语言切换到另外一种语言.对于跨国企业或者和国外有业务往来的公司特别重要:就算一个普通公司的门户如果支持中.英.繁体,也会让人觉得高大上.有没有呀, ...
- The SQL Server Service Broker for the current database is not enabled
把一个数据恢复至另一个服务器上,出现了一个异常: The SQL Server Service Broker for the current database is not enabled, and ...
- 模仿36。杀毒~button
<Style x:Key="360btn" TargetType="{x:Type Button}"> <Setter Property=&q ...
- Android ViewPager滑动背景渐变
原理 总 布局为RelativeLayout或者FrameLayout,在这里我们用的是RelativeLayout.先设置背景图片,宽度和高度都 fill_parent,在设置viewpager,v ...
- Win10 IoT C#开发 4 - UART 串口通信
Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,既可以开发设备UI与用户交互式操作,又可以控制GPIO等接口,使得原来嵌入式繁琐的开发变得简单.通过Remote Debug ...
- 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间
[源码下载] 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间 作者:webabcd 介绍速战速决 之 PHP 动态地创 ...
- swift变量和函数
func getNums()->(Int,Int){ //swift函数可以返回多个变量 ,) } let (a,b) = getNums() //let是常量,一旦赋值后不可改变, var是变 ...
- 使用插件实现一般处理程序导出excel
string sql = "select * from WJ_ProjectManager where" + WhereString ; DataTable dt = SqlHel ...