Android应用开发实战GPS与加速度传感器 android
本文将为读者详细介绍Android中加强现实应用程序的两个关键元素:GPS与加速度传感器。 git
所需工具 安全
下面是本文中将用到的工具: ide
如何与卫星通讯 函数
在实现了Android加强现实引擎的前两个元素即摄像头与指南针以后,下一步要作的就是肯定位置。为了完成这项任务,咱们主要用到Android的LocationManager对象。不过在此以前,咱们还需首先解决一些其余问题,其中权限是咱们首先要扫除的第一个障碍。 工具
Android的LocationManager支持两种权限请求: 布局
1. 须要告知系统您但愿取得用户的位置。 spa
2. 须要告诉它您想要十分详细的地理信息。 插件
您须要在AndroidManifest.xmlxml 文件标签内的标签中请求这两种权限,以下所示: 线程
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><uses-permission android:name="android.permission.LOCATION"/>
对于细粒度的位置更新,也就是近距离显示有关对象,还须要添加如下内容:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
若是没有这两行,当您试图注册位置更新时,Android就将返回一个安全异常,从而致使您的应用关闭。
获取位置管理器
得到位置管理器看起来好像挺简单的,可是仍是得牢记一些事项。首先,咱们也许只能在UI主线程中请求位置管理器。咱们要么在有关动做的onCreate调用中请求LocationManager对象,要么使用LocationManager请求建立一个运行于主线程的可执行对象。
为简单起见,下面的示例代码将从一个动做的onCreate方法中注册LocationManager更新。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->public void onCreate(Bundle savedInstanceState)
{
LocationManager locMan;
locMan =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER,
100, 1, gpsListener);
}
如您所见,这里声明了一个LocationManager对象,使用getSystemService得到您的对象,而后调用了requestLocationUpdates。
您可能想知道位置更新时须要哪些参数。首先,您告诉系统,您想使用系统中GPS装置的位置更新功能。而后,您告诉它您但愿多长时间更新一次(本例时间间隔为100ms),而且每当移动一米以上时就更新。这样,就能迅速识别他们的移动状况并调整它们与其余对象的位置关系。最后,传入实现LocationListener接口的类的实例。
位置更新的侦听艺术
为位置更新传递请求后,LocationListener类将收到初始位置,继之之后来位置的改变状况。下面是咱们的LocationListener:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->LocationListener gpsListener = new LocationListener(){
Location curLocation;
boolean locationChanged = false;
public void onLocationChanged(Location location)
{
if(curLocation == null)
{
curLocation = location;
locationChanged = true;
}
if(curLocation.getLatitude() == location.getLatitude() &&
curLocation.getLongitude() == location.getLongitude())
locationChanged = false;
else
locationChanged = true;
curLocation = location;
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
在上面的代码中,咱们惟一须要关心的就是onLocationChanged这个方法。然而,咱们还会介绍这个对象的其它方法,以便您将这个对象复制到您本身的代码中时可以了解它们。 一旦卫星锁定了这个设备,方法onLocationChanged就会被调用,以后每通过在请求更新时指定的时间间隔(本例中为100ms)后,就会调用一次。
每当位置更新时,都会带来一个Location对象。咱们经过这个类能够得到目标的经纬度,并完成许多重要事情。这里咱们最感兴趣的方法是getLatitude()、getLongitude()、bearingTo()与distanceTo()。使用这四个函数,咱们能够计算出任何随后的位置的方位角,并肯定出离您的距离有多远。
请求加速度传感器数据
为了实现咱们的加强现实引擎,最后还须要用到加速度传感器数据。不过,Android已经为咱们简化了这些数据的收集工做。在上一篇介绍加强现实技术的文章中,咱们的示例程序能够请求手机的方位,并调用位置管理器对象中的registerListener来检索指南针数据。咱们也可使用一样的技术来请求加速度传感器数据,咱们用来请求加速度传感器数据的代码以下所示:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->sensorMan = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
sensorMan.registerListener(listener,
sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
咱们调用了上下文对象(上述代码中为ctx)的getSystemService方法。下面是用于方向监听器与加速度传感器监听器的完整代码。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->private SensorEventListener listener = new SensorEventListener(){
public static volatile float direction = (float) 0;
public static volatile float inclination;
public static volatile float rollingZ = (float)0;
public static volatile float kFilteringFactor = (float)0.05;
public static float aboveOrBelow = (float)0;
public void onAccuracyChanged(Sensor arg0, int arg1){}
public void onSensorChanged(SensorEvent evt)
{
float vals[] = evt.values;
if(evt.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
float rawDirection = vals[0];
direction =(float) ((rawDirection * kFilteringFactor) +
(direction * (1.0 - kFilteringFactor)));
inclination =
(float) ((vals[2] * kFilteringFactor) +
(inclination * (1.0 - kFilteringFactor)));
if(aboveOrBelow > 0)
inclination = inclination * -1;
if(evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
aboveOrBelow =
(float) ((vals[2] * kFilteringFactor) +
(aboveOrBelow * (1.0 - kFilteringFactor)));
}
}
}
};
呵呵,这里的代码稍微有点多,下面咱们来了解一下。首先,要为监听器设置全部的值。这意味着,您能够随时能够向监听器查询指南针方位与手机倾角。这些值会随着您请求的更新的类型的不一样而有所变化。
而后,咱们会收到传感器信息,这时须要肯定出两种主要信息:
1. 手机指向
2. 屏幕相对于水平面的倾角
第一种信息称为方位角;第二种信息称为倾角。为了肯定这些值,第一个计算任务就是过滤出摄像头的指南针运动。这称为翻转过滤器(rolling filter)。变量direction用于指出手机顶部指向哪里,而非摄像头自己指向哪里,因此咱们须要进行一些校订。
第二个数学计算任务是利用翻转过滤器对斜度进行处理,从而获得一个以度为单位的度量值,其中水平的度量值为90,向上或向下半倾的度量值为45,垂直向上或垂直向下的度量值为0。注意,当得数为45的时候,咱们没法肯定手机究竟是向上倾斜,仍是向下倾斜。 这时加速度传感器就派上用场了。它可以肯定出倾角的正负,正值表示从水平线向上,复制表示从水平线向下。
简言之,咱们须要的东西都能从加速度传感器那里获得。
加强现实技术的构件
到目前为止,打造本身加强现实技术引擎所需的工具咱们已经所有介绍过了,您还须要的就是少量数学知识、一些Android版面布局和大量的精力了。若是您对打造加强现实应用程序的兴趣远胜于打造加强现实引擎自己的话,能够关注我当前正在为Android开发的一个开源的加强现实技术引擎。为了得到更多的进展状况,能够在Twitter上跟随twitter.com/androidarkit。
虽然我喜欢尽量把全部的数学和绘图代码放在一块儿,并将三种信息统一叠放到摄像头上,可是这些已经超出了本文的讨论范围。然而,本文加上上一篇文章,已经构成了对Android的指南针、摄像头预览、加速度传感器与GPS子系统进行了全面的介绍。如今,您已经具有了建立大型加强现实技术应用程序所需的所有构件。