Android方向传感器实践——自己动手做指南针

G6上运行的指南针程序

传感器(Sensor)系统可以让智能手机的功能更加丰富多彩,在Android系统中支持多种传感器。AndroidSensor系统涉及了Android的各个层次。

Android系统支持多种传感器,有的传感器已经在Android的框架中使用,大多数传感器由应用程序来使用。

Android传感器类型分为加速度、磁场、方向、光线、临近性、温度等,具体的如下表:

传感器

JAVA中的名称

本地接口名称

数值

加速度

TYPE_ACCELEROMETER

SENSOR_TYPE_ACCELEROMETER

1

磁力域

TYPE_MAGNETIC_FIELD

SENSOR_TYPE_MAGNETIC_FIELD

2

方向

TYPE_ORIENTATION

SENSOR_TYPE_ORIENTATION

3

陀螺

TYPE_GYROSCOPE

SENSOR_TYPE_GYROSCOPE

4

光线(亮度)

TYPE_LIGHT

SENSOR_TYPE_LIGHT

5

压力

TYPE_PRESSURE

SENSOR_TYPE_PRESSURE

6

温度

TYPE_TEMPERATURE

SENSOR_TYPE_TEMPERATURE

7

临近性

TYPE_PROXIMITY

SENSOR_TYPE_PROXIMITY

8

在程序中我们可以获取到移动设备上方向传感器、加速度传感器或其他传感器的信息,我们可以根据得到的数值与上一次得到的数值之间的关系来进行需要的操作。在指南针程序中我们主要需要获取方向的数据,因此我们在实验机上做了一个测试,获取了在不同情况下传感数值的变化规律。

水平放置示意图

下面是我们实验中测试到的数据(由于我们所用实验机HTCG6只支持方向传感器,我们只测试了方向传感器在不同状态下的数值变化关系):

手机状态

数值状态

数值范围

手机水平放置,顶部指向正

x、y、z方向值为0

0

水平逆时针旋转

x不断减少

360~0

水平顺时针旋转

x不断增大

0~360

当手机左侧抬起时

z不断减少

0~-180

当手机右侧抬起时

z不断增大

0~180

当手机顶部抬起时

y不断减少

0~-180

当手机底部抬起时

y不断增大

0~180

*注意:实验数据是基于实验机型号(HTCG6),其它型号的设备可能会有所不同。

经过实验,我们发现当手机顶部指向正北方时方向值为0,顶部指向正东方时方向值为90,顶部指向正南方时方向值为180,顶部指向正西方时方向值为270。根据这些数据我们就可以根据方向值的范围盘端当前我们的方位,可以确定指南针的读数。

指南针程序界面

程序界面非常简洁,一张指南针的图片与相关方位的度数。上方白色小箭头所指方向代表我们当前指向的方向。指南针图片会根据所向方位做出相应的旋转,上方度数也会做出适当的响应,显示当前方位和方向读数。

由于我只考虑在G6上能正常演示,G6的屏幕分辨率为320*480,相关的坐标值我也是根据这个分辨率确定的,移植到其他型号的手机上可能不能正常运行,但只需要修正一下代码就可以,这个希望读者自行修正。

具体步骤如下:

1.首先创建项目SDK版本选择2.1,工程命名为MyCompass

2.添加资源到res/drawable下,一张指南针的图片和白色小箭头图片,格式为透明PNG,注意图片文件名需要小写开头。

3.新建一个CompassView类,用于程序布局设置。

4.新建MyCompass类,这为主程序,在该类中获取传感器信息。

下面附上CompassView类和MyCompass类的代码,同时提供源程序的下载,如果有什么问题的话随时可以与我联系,我的qq:264965161,电子邮箱gsh0913@qq.com,本人非常乐意与大家一起交流,希望大家能共同进步。

源代码的下载地址:http://download.youkuaiyun.com/source/2885661

CompassView.java

package com.app; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.view.View; public class CompassView extends View implements Runnable { private Paint _mPaint = new Paint(); private String _message = "正北 0°"; private float _decDegree = 0; private Bitmap _compass; private Bitmap _arrow; public CompassView(Context context) { super(context); // 载入图片 _compass = BitmapFactory.decodeResource(getResources(), R.drawable.compass); _arrow = BitmapFactory.decodeResource(getResources(), R.drawable.arrow); // 开启线程否则无法更新画面 new Thread(this).start(); } protected void onDraw(Canvas canvas) { canvas.drawColor(Color.BLACK); _mPaint.setColor(Color.WHITE); _mPaint.setTextSize(30); _mPaint.setFlags(Paint.FAKE_BOLD_TEXT_FLAG); canvas.drawText(_message, 75, 50, _mPaint); // 实现图像旋转 Matrix mat = new Matrix(); mat.reset(); mat.setTranslate(15, 100); mat.preRotate(-_decDegree, 145, 145); // 绘制图像 canvas.drawBitmap(_compass, mat, _mPaint); canvas.drawBitmap(_arrow, 152, 73, null); } @Override public void run() { while(!Thread.currentThread().isInterrupted()) { try { Thread.sleep(100); } catch(InterruptedException e) { Thread.currentThread().interrupt(); } postInvalidate(); } } // 更新指南针角度 public void setDegree(float degree) { // 设置灵敏度 if(Math.abs(_decDegree - degree) >= 2 ) { _decDegree = degree; int range = 22; String degreeStr = String.valueOf(_decDegree); // 指向正北 if(_decDegree > 360 - range && _decDegree < 360 + range) { _message = "正北 " + degreeStr + "°"; } // 指向正东 if(_decDegree > 90 - range && _decDegree < 90 + range) { _message = "正东 " + degreeStr + "°"; } // 指向正南 if(_decDegree > 180 - range && _decDegree < 180 + range) { _message = "正南 " + degreeStr + "°"; } // 指向正西 if(_decDegree > 270 - range && _decDegree < 270 + range) { _message = "正西 " + degreeStr + "°"; } // 指向东北 if(_decDegree > 45 - range && _decDegree < 45 + range) { _message = "东北 " + degreeStr + "°"; } // 指向东南 if(_decDegree > 135 - range && _decDegree < 135 + range) { _message = "东南 " + degreeStr + "°"; } // 指向西南 if(_decDegree > 225 - range && _decDegree < 225 + range) { _message = "西南 " + degreeStr + "°"; } // 指向西北 if(_decDegree > 315 - range && _decDegree < 315 + range) { _message = "西北 " + degreeStr + "°"; } } } // 更新指示信息 public void setMessage(String message) { _message = message; } }

MyCompass.java

package com.app; import java.util.List; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; public class MyCompass extends Activity implements SensorEventListener { private CompassView _compassView; private boolean mRegisteredSensor; //定义SensorManager private SensorManager mSensorManager; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); _compassView = new CompassView(this); setContentView(_compassView); mRegisteredSensor = false; //取得SensorManager实例 mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); } @Override protected void onResume() { super.onResume(); //接受SensorManager的一个列表(Listener) //这里我们指定类型为TYPE_ORIENTATION(方向感应器) List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION); if (sensors.size() > 0) { Sensor sensor = sensors.get(0); //注册SensorManager //this->接收sensor的实例 //接收传感器类型的列表 //接受的频率 mRegisteredSensor = mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST); } } @Override protected void onPause() { if (mRegisteredSensor) { //如果调用了registerListener //这里我们需要unregisterListener来卸载/取消注册 mSensorManager.unregisterListener(this); mRegisteredSensor = false; } super.onPause(); } //当进准度发生改变时 //sensor->传感器 //accuracy->精准度 @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } // 当传感器在被改变时触发 @Override public void onSensorChanged(SensorEvent event) { // 接受方向感应器的类型 if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) { // 这里我们可以得到数据,然后根据需要来处理 float x = event.values[SensorManager.DATA_X]; _compassView.setDegree(x); } } }

<!--EndFragment-->

<!--EndFragment-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值