当前位置:文档之家› Android重力感应

Android重力感应

手机的感应器在Android里边所代表的类是Sensor,你只要看到在android.hardware这个包下边的都是封装的关于一些特殊的硬件方面的类,比如说Camera、Sensor之类的。

一直都很怀疑为什么HTC的Google手机没有前置摄像头。

怨念啊。

PS:虽然是2.1的机子,但是我用的是1.5的SDK。

代码很简单:我们首先要得到一个手机上的传感器。

Java代码
1.SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
这行代码只要用过类似开发的都应该知道是什么。

getSystemService(String name)可以用来返回一个硬件设备的控制器。

比如说LocationManage(和GPS相关用来确定位置的)、TelephonyManage(查询电话相关内容,比如说IMEI码)、AudioManager(顾名思义,是视频播放用的)等等。

具体可以观看SDK文档里边Activity的讲解。

/int ... d/app/Activity.html
得到重力感应的硬件控制了,然后我们就应该得到一个Sensor了。

Java代码
1.Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ALL);
关于这个参数。

其实挺复杂的。

我开始用的是TYPE_ALL,出的是XYZ三条轴线的偏移量,至于其他的大家可以看下边:
下边是官方SDK中对于各种类型的解析(粗体红字是我加上去的)
<!-- =========== ENUM CONSTANT SUMMARY =========== -->
Constants
int TYPE_ACCELEROMETER
A constant describing an accelerometer sensor
type.加速度
int TYPE_ALL A constant describing all sensor types.所有类型,NexusOne 默认为 加速度
int TYPE_GYROSCOPE A constant describing a gyroscope sensor type 回转仪(这个不太懂)
int TYPE_LIGHT A constant describing an light sensor type.光线感应吗
int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type.磁场
int TYPE_ORIENTATION A constant describing an orientation sensor type.定向(指北针)和角度
int TYPE_PRESSURE A constant describing a pressure sensor type 压力计
int TYPE_PROXIMITY A constant describing an proximity sensor type.距离?不太懂
int TYPE_TEMPERATURE A constant describing a temperature sensor type 温度啦
然后就是我们需要即时了解手机的偏转度。

以TYPE_ALL 为例子。

(其实就是TYPE_ACCELEROMETER )
PS :有时候你的机子并不会拥有这么全的感应装置,这个时候你应该再进行以下判断。

比如说: Java 代码
1. Sensor sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
2.
3. if (sensor == null ){
4. log.w("NO_SERVICE","没有感应温度的感应装置。

")
5. ... ...
6. }else {
7. ... ...
8. }
所有最基本的三维坐标系有三个轴:X、Y和Z,这个学过矩阵或者线性代数的都应该知道吧
(~~~~(>_<)~~~~ 我当年线性代数挂了。

惨不忍睹啊。

后来自学DirectX的时候才觉得原来矩阵变换是这么的重要。

而且更重要的是这个一点也不难吗。


关于手机的XYZ坐标,把你的手机平放到桌子上,横x,纵y,然后z就是屏幕法线。

官方的例子:(直接粘贴的话空格会变小,所以就截图了)
然后我们注册一个Listener,用来监听我们所得到的值的改变。

Java代码
1.SensorEventListener lsn = new SensorEventListener() {
2.public
void onSensorChanged(SensorEvent e) {
3.x = e.values[SensorManager.DATA_X];
4.y = e.values[SensorManager.DATA_Y];
5.z = e.values[SensorManager.DATA_Z];
6.t.setText("x=" + Math.round(x * ROUND_NUMBER) + "," + "y="
7. + Math.round(y * ROUND_NUMBER) + "," + "z="
8. + Math.round(z * ROUND_NUMBER));
9. }
10.
11.public
void onAccuracyChanged(Sensor s, int accuracy) {
12. }
13. };
在这里我把数字放大了,我预先定义了一个变量ROUND_NUMBER,是为了以后用来更改灵敏度的。

我取的值是100。

这个就简单了,我们首先声明一个SensorEvent的监听,每当它得到的值改变的时候,我就在一个TextView t上边输出改变了的值。

在这里使用TYPE_ALL返回的值SensorEvent里边的values就是得到的数字。

得到的values默认是一个float[]。

也就是说是一个float类型的数组。

他在TYPE_ALL的声明下一共返回三个值,分别就是x、y、z轴的值,假如你将手机平放在水平面上,默认分别是0,0,10。

(我在网上查到有的人和我得到的数字不一样,有人说是0,0,-10,关于这个我不知道是为什么,如果有人的Gphone 比较多的话可以看看是怎么一回事),而当你将手机垂直立起,显示的应当是0,10,0。

PS:SensorManager里边有很多的有意思的常量,比如说SensorManager.GRAVITY_EARTH是地球的重力加速度,当然也有GRAVITY_MARS火星的,GRAVITY_MOON月球的,最恶搞的还有GRAVITY_DEATH_STAR_I(星球大战里的卫星武器死星I号)。

还有一个
GRAVITY_THE_ISLAND,这个不知道是哪里。

汗。

难道是《岛》这本书里的世界?还是Neverland?
然后我们可以给Manager注册一个监听。

Java代码
1.sensorMgr.registerListener(lsn, sensor,
2.SensorManager.SENSOR_DELAY_GAME);
三个参数分别是监听,感应装置,和灵敏度。

灵敏度分为:
SENSOR_DELAY_FASTEST最灵敏,快的然你无语
SENSOR_DELAY_GAME游戏的时候用这个,不过一般用这个就够了,和上一个很难看出区别(也许是我的手机CPU高?1GHz的。


SENSOR_DELAY_NORMAL比较慢。

SENSOR_DELAY_UI 最慢的,几乎就是横和纵的区别
也许有些人想要拿这个来练练手了。

比如说是现在每天播放的联通iPhone广告里有一个“可以用来测量相框水平”这个广告词。

但是,但是。

恩恩。

输出的最好还是角度比较好吧?
所以我们改一改,做一个基本的LevelBar。

没有什么图形界面,只是用来输出。

我们首先注册的Sensor应该改了。

不是TYPE_ALL,而是TYPE_ORIENTATION !
然后剩下的基本上都一样。

SensorEvent返回的values也是三个值的数组。

但是,这三个值还是稍微有些不同的,如果你看了输出的值,那么就可能会明白了。

首先是第一个,有些人发现就算是平放在桌面上第一个值也会变,那么,第一个值其实不是轴角度,而是方向。

对了,这就是我在随上边写的指北针!当数字是0的时候,你的手机指向的是正北方向,90的话是东,180是南,270是西。

这下子,再加上一个漂亮的图形界面,一个指南针软件就可以出来了吧。

然后是第二个和第三个,就是x,y轴的角度值!对,是角度值而且不用换算。

这样子,你可以把屏幕横过来,然后直接输出y轴的角度值了,什么时候他是90度,那么就是水平了!。

相关主题