Android平台上使用气压传感器计算海拔高度

  气压传感器两年前已经开始被手机制造商运用在其设备上,但貌似没有引起开发者足够的重视。像Galaxy S III 、Galaxy Note 2和小米2手机上都有,不过大家对于气压传感器比较陌生。其实大气压无处不在,我们可以利用它来为我们完成诸如海拔高度测量甚至是空间定位的任务。

  先说些题外话,舒缓一下工作学习的疲惫。前些天跟朋友一起去户外活动,登山到半山腰,突然朋友问我,现在海拔大概多少?我脑子灵光一闪,前些天一个在小米工作的朋友在其小米2手机上打开指南针应用对我说现在海拔多少多少,而我现在手头正有一台小米4手机,赶紧拿出来打开指南针应用,结果气压是出来了,海拔计算却需要联网,真是让人扫兴。也正是这一点让我萌生了自己来计算的想法。

  既然说做,那就做吧,反正应该不会太难。首先网上查询相关资料,计算自己的海拔高度通常有两种方法,一是通过GPS全球定位系统,二是通过测出大气压,然后根据气压值计算出海拔高度。

  使用GPS全球定位系统获取海拔简单是简单,只要获取到Android系统提供LoctionManager服务,将提供者设置为LocationManager.GPS_PROVIDER,在写个GPS状态监听器GpsStatus.Listener,最后在实现一个LocationListener来实时监听位置的变化,在onLocationChanged回调函数中取出location参数,里面就包含了海拔高度值(getAltitude())。关键代码如下

 1 private LocationManager lm;
 2 lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
 3 if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
 4     Log.i(TAG, "请先开启GPS");
 5     showAlertDialog(context, "开启GPS,定位更准确;取消则使用网络定位,粗略定位");
 6 }
 7 if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
 8     Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
 9      context.startActivity(intent);
10 }
11 lm.addGpsStatusListener(listener);
12 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, locationListener);

  其中listener和locationListener分别为StatusListener和LocationListener的实例,使用起来也不难,主要代码框架已经为你生成了,只要查查android SDK的API就会明白的,就不说了。这种方式去测海拔,需要接收GPS信号。如果你在丛林或者洞穴或建筑物内,极有可能是接收不到GPS卫星信号的。这时候,可以考虑使用压力传感器来测海拔高度。

  先说说使用压力传感器来测海拔高度的原理,其实非常简单,一些基本原理你必须要明白的:一般来说海拔越高,气压越低,他们之间存在某种关系,下文会讲到的。有不少学者对海拔与气压做了研究,回归了不少海拔与气压的数据,他们的变化关系大概服从下面的表达式。

  因为我们要计算海拔(A),所以略作变化,可以知道A的计算公式如下。

  其中P为当前的大气压,P0为标准大气压。这样,我们只要获取Android手机内置气压传感器的值,就可以初步估算出海拔高度了。实现起来也不难,关键代码如下。

1 private SensorManager sensorManager = null;
2 sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
3 mPressure = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
4 if(mPressure == null)
5 {
6     mPressureVal.setText("您的手机不支持气压传感器,无法使用本软件功能.");
7     return;
8 }
9 mAccelerate = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

  然后在onResume()函数里面注册气压传感器,在onPause()中注销,这样做当然是为了节约用电嘛。

sensorManager.registerListener(pressureListener, mPressure,
        SensorManager.SENSOR_DELAY_NORMAL);
if(pressureListener!=null){
    sensorManager.unregisterListener(pressureListener);
}    

  还有一点必须获取气压传感器的值嘛,必须要有一个SensorEventListener对象(SensorManager注册语句的pressureListener),代码很简单。

 1 SensorEventListener pressureListener = new SensorEventListener() {
 2
 3     @Override
 4     public void onSensorChanged(SensorEvent event) {
 5         // TODO Auto-generated method stub
 6         float sPV = event.values[0];
 7         mPressureVal.setText(String.valueOf(sPV));
 8         DecimalFormat df = new DecimalFormat("0.00");
 9         df.getRoundingMode();
10         // 计算海拔
11         double height = 44330000*(1-(Math.pow((Double.parseDouble(df.format(sPV))/1013.25),
12                 (float)1.0/5255.0)));
13         mAltitude.setText(df.format(height));
14     }
15
16     @Override
17     public void onAccuracyChanged(Sensor sensor, int accuracy) {
18         // TODO Auto-generated method stub
19
20     }
21 };

  海拔计算公式的实现自然也不是难事,基本上是翻译一下就出来了。

  其实海拔和气压的这种关系比较复杂,受多方面的因素影响,最为显著的是温度的影响。大气压通俗来讲是大气对其他物体的压力,与空气分子的密度和动能相关,所以同一海拔高度,温度越高,气压越高。正是因为这个影响因素,使得气压测海拔有较明显的误差。如果是时隔不久,即温度变化不大,测高度差还是比较准确的,我做过实验,利用气压能较为准确的测出7层楼的高度,哈哈,是不是感觉很灵敏呢?只是影响因素带来的误差还得想办法消除。刚接触Android不久,也没写过什么博客,这个纯属扯扯,没什么技术难度,仅仅是为了总结一下android开发的一些事儿,顺便练练笔而已。

时间: 2024-12-13 17:53:54

Android平台上使用气压传感器计算海拔高度的相关文章

Android平台上裁剪m4a

Android手机上设置铃声的操作是比较灵活的,一般读者听到一首喜欢的歌曲,马上就可以对这首歌曲进行裁剪,裁剪到片段后,再通过系统的接口设置为铃声(电话铃声.闹钟铃声等). 前提是,播放这首歌的APP,需要提供裁剪歌曲的功能. 那么,怎么样实现截取音频文件的一个片段的功能呢? 小程很自然就想到使用FFmpeg命令来实现,之前介绍"从视频中提取图片"的内容就可以提取片段,比如: ffmpeg -ss 10 -i audio.mp3 -t 5 out.mp3上面的命令,从第10秒开始,提取

如何在android平台上使用js直接调用Java方法[转]

转载自:http://www.cocos.com/docs/html5/v3/reflection/zh.html #如何在android平台上使用js直接调用Java方法 在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parame

【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callStaticMethod方法中,我们通过传入Java的类名,方法名,方法签名,参数就可以直接调用Java的静态方法,并且可以获得Java方法的返回

Android平台上抓包

经常会有一些测试需求比如:测试手机上某个app的网络通信是否已经加密,或者测试某个app是否偷偷链接某些网站. 根据抓包的对象,主要有两种途径: 1. 在路由器端抓包:使用一台已经连入路由器的PC来抓取路由器上所有的数据传输信息. 2. 在终端抓包:在终端(手机,平板等)上抓取次终端设备的网络传输信息. 注意:可以很容易通过网络下载到很多可以用来抓包的apk,但是前提是android手机或者终端要root过,笔者试过其中的一.二款,感觉不够理想. 其实网上的这些工具也都是使用tcpdump这款命

Android平台上关于IM的实践总结

前言 IM通信在互联网发展到现在已经是码农的世界里人尽皆知的技术,特别在当下移动互联网迅猛发展的时代这种技术的开发也更加火热,其中老牌的代表作就有QQ和MSN,和最近新崛起的微信,默默,易信,来往等眼花缭乱的各种应用都把IM技术应用其中.我是Android开发人员,写这篇文章主要原因也是因为我自己从事开发以来主要做过的几款APP都是包含着IM通信,在不断的摸爬滚打的解决问题的过程中,积累了一些经验记录便将其记录到博客中作为自己一个阶段性的总结,也可以分享其他需要的开发者,作为一种参考实践的方案,

Freeline - Android平台上的秒级编译方案

FreeLine是什么? Freeline是蚂蚁金服旗下一站式理财平台蚂蚁聚宝团队15年10月在Android平台上的量身定做的一个基于动态替换的编译方案,5月阿里集团内部开源,稳定性方面:完善的基线对齐,进程级别异常隔离机制.性能方面:内部采用了类似Facebook的开源工具buck的多工程多任务并发思想:端口扫描,代码扫描,并发编译,并发dx,并发merge dex等策略,在多核机器上有明显加速效果,另外在class及dex,resources层面作了相应缓存策略,做到真正增量开发,另外引入

Android平台上最好的几款免费的代码编辑器

使用正确的开发工具能够快速有效地完成源代码的编写和测试,使编程事半功倍.在网络信息高速发展的今天,移动设备的方便快捷已经深入人心,越来越多的程序员会选择在任何感觉舒适的地方使用移动设备查看或者编辑源代码.于是,Android平台上大量基于代码编程的应运而生,谷歌应用商店里的代码编辑器.编译器和开发环境比比皆是.由于不同的工具特性和缺点不尽相同,因此如何选择一款最适合自己的开发工具便成了一件头疼的事情.在这里,我们列出了Android平台上5款最好的代码编辑器来帮助你作出选择. 1. Quoda

在Android平台上编译faad2

1.从官网下载源码 2.编辑一个config.h: /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Define if you want to use libfaad together with Digital Radio Mondiale (DRM) */ /* #undef DRM */ /* De

cocos js js java互调 (如何在ANDROID平台上使用JS直接调用JAVA)

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callStaticMethod方法中,我们通过传入Java的类名,方法名,方法签名,参数就可以直接调用Java的静态方法,并且可以获得Java方法的返回