今天讲一下方向感应器,首先讲一下感应器这个概念。

Android的大概支持八种感应器。像陀螺仪、重力(加速度)感应器,磁力感应器,温度感应器,方向感应器,光线感应器等。他们有统一的类管理一个是Sensor类,一个是SensorManager类,还有其他的一些类,好像就磁力感应器有一个自己单独的类。这里不细说了。


再将一下方向感应器,也有人称为姿态感应器,主要的作用是通过3个数据来反映手机的姿态。大家知道三维空间中有六个方向,东南西北上下,可以化为X、Y、Z坐标系,我们以手机中心为原点,手机与3个平面(XOY, XOZ ,YOZ)的夹角级是方向感应器感应的数据了。这三个数据由表示3个角度,Azimuth,Pitch,Roll。


这三个角度又是什么呢?这里我们做过小实验,首先把手机放在一水平平面(如桌面),然后将机顶抬起来,这里变化幅度较大的是Pitch,也就是说机顶与机尾连线与水平面所成的角度即为Pitch。然后放平手机,在将左侧抬起,这时变化较大的是Roll,即左右边连线与水平面所成夹角为Roll。把手机放平,然后推到手机一角,使手机在平面上转动,这时变化较大的是Azimuth。


好了,了解这些基本概念了,开始编程了。


这个是布局文件,相信你懂得 ^_^


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv1"
        />
    
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv2"
        />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv3"
        />

</LinearLayout>




然后是Activity文件


package com.wang;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class OrientationActivity extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
	TextView tv1;
	TextView tv2;
	TextView tv3;
	float[] data = new float[3];		//获取方向感应器传入的数据
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        tv1 = (TextView)findViewById(R.id.tv1);
        tv2 = (TextView)findViewById(R.id.tv2);
        tv3 = (TextView)findViewById(R.id.tv3);
        SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor gsensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        sm.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
    }
    public void onSensorChanged(SensorEvent event){
    	
    	if(event.sensor.getType()==Sensor.TYPE_ORIENTATION){
    		data=event.values;
    		tv1.setText("Azimuth="+data[0]);
    		tv2.setText("Pitch="+data[1]);
    		tv3.setText("Roll="+data[2]);
    		
    		Log.v("orientation", "Azimuth="+data[0]);
    		Log.v("orientation", "Pitch="+data[1]);
    		Log.v("orientation", "Roll="+data[2]);
    	}
    }
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}
}




稍微解释一下,想要使用感应器就要先定义感应器类型,由SensorManager给出,其实大部分的计算操作都是由SensorManager来做的,这里是个简单例子就没什么计算了。


SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor gsensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);



注册监听器,其实是表明要获取数据了,并给出怎样获取。


sm.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);



第一个参数是所继承接口的指针,所以这个接口一定要有的,第二个是哪个感应器接收数据,第三个是接收的频率,我们一般都选GAME的这个级别,有四个级别,不过一般就用这个就够了。


然后要实现接口中的方法,这里主要是这个方法。

public void onSensorChanged(SensorEvent event)



当接收的数据有变化时就会调用,不同的感应器,接收的数据是不同的,这里的方向感应器主要是三个角度的数据。


好了,我想这个例子够简单吧,不过我在网上找了很多资料,还真没找到一个像样的例子处理,都是各种支离破碎的,而且看起来超复杂,现在稍微懂一点的时候,发现并不是那样复杂。


再将一下游戏吧,个人觉得想赛车类游戏做这种转向感应的,如果要求精度不够的话,没必要用什么陀螺仪、磁力感应器什么的,哪些都是应用于卫星定位、航海等软件的。我们用个方向感应器就差不多了,还简单,计算量小,当然这个纯属个人观点了。毕竟被人能力也有限。