应用JNI技术在Java中读取ThinkPad重力感应蕊片实时数据

来源:互联网 发布:小学认字软件 编辑:程序博客网 时间:2024/06/02 14:22

ThinkPad的品质是众所周知,多年来一直是品质的象征,至少在LENOVO收购之前是这样的,它一惯是一身黑衣示人,所以大家都叫它“小黑”。尤其受IT专业人士青睐。小黑迷们的狂热是不无道理的,它本身有很多创新的设计、良好的散热系统,人性化的管理软件很让人省心。其中一项独特的设计就是:APS主动保护系统,它是为了防止笔记本意处跌落对硬盘造成伤害,从而保护你保贵的数据。

 

曾经在网上看过一个视频,讲的是国外一个网友读取到aps中的重力感应蕊片的数据,然后摇晃笔记本来控制方向,用它来玩企鹅滑雪的游戏。当时感觉挺有意思的,不过不要玩的太激烈,因为你再晃动地时候,他本身的APS系统的保护机制会不断的将硬盘磁头归位。今年在出差回去休息的时候,突然又想起来了,看看我的T61,何不我也来试试。后来经过断断续续研究,原来他调用的编程接口,是在一个sensor.dll的动态链接库里,只要本本上有aps保护系统,都会在system32目录下找到。后来在网上找到一段C#的例子,参考了一下所返回的数据结构,我就在C下面把它给实现了。

 

身边很多人都不熟悉C/C++程序,因为工作后一直用Java,用C类语言来做开发很少,所以,为了方便熟悉java的朋友,我就索性用JNI接口,把它在java里实现了。Jni(java native interface)就是java平台的一部分,对jni概念不清楚的朋友可以去baidu/google, http://baike.baidu.com/view/1272329.htm,这个标准就是充许java与本地其它语言代码进行交互。在调用本地代码之前,应该先按照JNI标准进行java代码的设计,首先,我写了一个调用jni接口的类。代码如下:

 

package jni;

/**

 * 获得ThinkPad重力感应蕊片数据的JNI接口类

 * @Project jni_sensor

 *

 * @author ZhaoYanjun

 * Aug 16, 2009

 */

public class ApsSensor {

    static{

       System.loadLibrary("jni_sensor");

    }

    /**

     * 获得ThinkPad重力感应蕊片数据的接口方法

     * 返回SensorData实例,对应感应数据的结构体

     * @return SensorData

     *

     */

    public synchronized native static SensorData genSensorData();

}

其中,System.loadLibrary("jni_sensor");是你在定义的要载入的按照jni标准编写生成的动态链接库的名字。定义了一个jni接口方法genSensorData(),他所返回是一个对象SensorData,这个对象带有通过jni读取到的重力感应蕊片的数据。感应数据类SensorData的代码如下:

package jni;

/**

 * 重力感应蕊片状态值

 * @Project jni_sensor

 *

 * @author ZhaoYanjun

 * Aug 16, 2009

 */

public final class SensorData {

    /**

     * 幅度范围(敏感度)

     */

    public static float RANGE = 25;

    /**

     * 重力感应蕊片的状态值

     * 0:稳定

     * 1,2,3,4:运行/活动

     * 8,9:暂停

     * 13:忽略正常的频繁震动

     * 14:不可用

     * 其它:未知

     */

    public short status;

    /**

     * 当前实时状态X

     */

    public short rawDataX;

    /**

     * 当前实时状态Y

     */

    public short rawDataY;

    /**

     * 最新状态平均X

     */

    public short averDataX;

    /**

     * 最新状态平均Y

     */

    public short averDataY;

    /**

     * 温度值(暂不能用)

     */

    public short temperature;

    /**

     * 最新稳定后的X

     */

    public short latestZeroX;

    /**

     * 最新稳定后的Y

     */

    public short latestZeroY;

   

    public SensorData(){

    }

    /**

     * 是否右倾斜

     * @return boolean

     *

     */

    public boolean isRight(){

       if(this.averDataY>(this.latestZeroY+SensorData.RANGE)){

           return true;

       }

       return false;

    }

    /**

     * 是否左倾斜

     * @return boolean

     *

     */

    public boolean isLeft(){

       if(this.averDataY<(this.latestZeroY-SensorData.RANGE)){

           return true;

       }

       return false;

    }

    /**

     * 是否前倾斜

     * @return boolean

     *

     */

    public boolean isForward(){

       if(this.averDataX<(this.latestZeroX-SensorData.RANGE)){

           return true;

       }

       return false;

    }

    /**

     * 是否后倾斜

     * @return boolean

     *

     */

    public boolean isBack(){

       if(this.averDataX>(this.latestZeroX+SensorData.RANGE)){

           return true;

       }

       return false;

    }

}

其中ApsSensor类,按照jni标准编写好后,需要调用jdk/bin下面的javah.exe,将jni java类生成扩展名为h的头文件,javah.exe –jni –classpath,在本例中生成的h文件名为jni_ApsSensor.h。它里面定义就是一个按照jni标准生成的C接口方法的定义,这个名字不能随便修改,修改后java调用时就不起作用。你只能把它加到C的源程序里,来实现它。如果你的jni java类的方法改变那必须重新生成这个.h文件。

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class jni_ApsSensor */

 

#ifndef _Included_jni_ApsSensor

#define _Included_jni_ApsSensor

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     jni_ApsSensor

 * Method:    genSensorData

 * Signature: ()Ljni/SensorData;

 */

JNIEXPORT jobject JNICALL Java_jni_ApsSensor_genSensorData

  (JNIEnv *, jclass);

 

#ifdef __cplusplus

}

#endif

#endif

.h文件加到C的源程序并实现后,生成相应的dll文件,在本例中生成的dll文件为jni_sensor.dll,也就是跟你在jni java类中定义的一样的,System.loadLibrary("jni_sensor");

生成dll文件后,将它放system32目录下,或jdk/bin下面,只要path路径能找到的位置就可以,在本例中将jni_sensor.dl放在了我的jdk/bin下面。然后写了一段代码来测试一下是否读到了数据。

package jni;

/**

 *

 * @Project jni_sensor

 *

 * @author ZhaoYanjun

 * Aug 20, 2009

 */

public class SensorMain {

 

    /**

     * @param args

     *

     */

    public static void main(String[] args) {

      

       Object obj = new Object();

       try {

           synchronized (obj) {

              while (true) {

                  SensorData sdata = ApsSensor.genSensorData();

 

                  if(sdata.isForward()){

                     System.out.println("Forward!");

                  }

                  if(sdata.isBack()){

                     System.out.println("Back!");

                  }

                  if(sdata.isLeft()){

                     System.out.println("Left!");

                  }

                  if(sdata.isRight()){

                     System.out.println("Right!");

                  }

                  //System.out.println("status:"+sdata.status);

                  obj.wait(100);

              }

           }

       } catch (Exception ex) {

           ex.printStackTrace();

       }

    }

 

}

然后,拿起我的T61,前、后、左、右做运动,吼吼结果出现了。

 

 

 

  到此,我们在java中调用ThinkPad重力感应蕊片的实时数据完成了。我把生成的jni_sensor.dll文件和打好的jar传上来。只要把dll文件放到system32目录下面,在你的程序中调用jar中相应的方法就可以了。当然,只有thinkpad笔记本且有APS功能才可以。估计T系列的都带有这个aps主动保护系统。

  jar包和jni_sensor.dll:http://d.download.csdn.net/down/1592250/June126

    在接下的文章里,我会介绍如何在C中读取重力感应蕊片的实时数据。

原创粉丝点击