Android开发10:传感器器及地图相关应用

前言

  啦啦啦~各位小伙伴们好~经过这一学期的Android知识的学习,我们学到了很多和Android开发相关的知识,这一学期的学习也要告一段落了。(博客中有很多照片上有代码,代码文本较小,各位可按下Ctrl和前滚轮放大后再看~)

  一起进入我们今天的相关内容~这次我们将一起学习使用 android 手机不同的传感器,包括磁强计、加速度传感器等。学会使用 android 位置服务获得经纬度信息。学会使用百度地图基础API进行地图应用的开发。

 

基础知识

一、传感器简介

      手机中内置的传感器是一种微型的物理设备,它能够探测、感受到外界的信号,并按一定规律转换成我们所需要的信息。Android 手机通常都会支持多种类型的传感器,如光照传感器、加速度传感器、地磁传感器、压力传感器、温度传感器等。

      当然,Android 系统只是负责将这些传感器所输出的信息传递给我们,至于具体如何去利用这些信息就要充分发挥开发者的想象力了。

二、Android传感器框架

  Android SDK为我们提供了ASF,可以用来访问当前Android设备内置的传感器。ASF提供了很多类和接口,帮助我们完成各种与传感器有关的任务。例如:

1)确定当前Android设备内置了哪些传感器。

2)确定某一个传感器的技术指标。

3)获取传感器传回来的数据,以及定义传感器回传数据的精度。

4)注册和注销传感器事件监听器,这些监听器用于监听传感器的变化,通常从传感器回传的数据需要利用这些监听器完成。

  ASF允许我们访问很多传感器类型,这些传感器有一些是基于硬件的传感器,还有一些是基于软件的传感器。基于硬件的传感器就是直接以芯片形式嵌入到Android设备中,这些传感器直接从外部环境获取数据。基于软件的传感器并不是实际的硬件芯片,基于软件的传感器传回的数据本质上也来自于基于硬件的传感器,只是这些数据通常会经过二次加工。所以基于软件的传感器也可以称为虚拟(virtual)传感器或合成(synthetic)传感器。

  Android对每个设备的传感器都进行了抽象,其中SensorManger类用来控制传感器,Sensor用来描述具体的传感器,SensorEventListener用来监听传感器值的改变。

 

(1)SensorManager类

  用于创建sensor service的实例。该类提供了很多用于访问和枚举传感器,注册和注销传感器监听器的方法。而且还提供了与传感器精度、扫描频率、校正有关的常量。

(2)Sensor类

  Sensor类为我们提供了一些用于获取传感器技术参数的方法。如版本、类型、生产商等。例如所有传感器的TYPE类型如下:

序号传感器Sensor类中定义的TYPE常量
1 加速度传感器 TYPE_ACCELEROMETER
2 温度传感器 TYPE_AMBIENT_TEMPERATURE
3 陀螺仪传感器 TYPE_GYROSCOPE
4 光线传感器 TYPE_LIGHT
5 磁场传感器 TYPE_MAGNETIC_FIELD
6 压力传感器 TYPE_PRESSURE
7 临近传感器 TYPE_PROXIMITY
8 湿度传感器 TYPE_RELATIVE_HUMIDITY
9 方向传感器 TYPE_ORIENTATION
10 重力传感器 TYPE_GRAVITY
11 线性加速传感器 TYPE_LINEAR_ACCELERATION
12 旋转向量传感器 TYPE_ROTATION_VECTOR

  注意:1-8是硬件传感器,9是软件传感器,其中方向传感器的数据来自重力和磁场传感器,10-12是硬件或软件传感器。

(3)SensorEvent类

  系统使用该类创建传感器事件对象。该对象可以提供与传感器事件有关的信息。传感器事件对象包括的信息有原始的传感器回传数据、传感器类型、数据的精度以及触发事件的时间。

(4)SensorEventListener接口

该接口包含两个回调方法,当传感器的回传值或精度发生变化时,系统会调用这两个回调方法。

/**
 * 传感器精度变化时回调
 */
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
 * 传感器数据变化时回调
 */
@Override
public void onSensorChanged(SensorEvent event) {
}

 到了这里,我们就可以进行传感器开发工作了。

 

实验内容

本次实验主要是涉及传感器及地图相关应⽤,实现简单的地图功能。

实现最终结果实现效果如图所示:

    

                                             实验效果图

 

主要分为以下三部分

a) 调用百度地图SDK实现地图的展示以及交互,其中包括左下角的按钮要求实现的功能如下:

i. 当按钮处于状态时:如果GPS位置有更新,那么更新用户当前所在位置,并使得当前位置的箭头图标一直保持在屏幕中心。

ii. 按钮处于 状态时,更新当前位置的箭头的时候不移动地图。

iii. 点击按钮可以切换这两种状态,当按钮进入状态的时候,使得表示当前位置的箭头位于屏幕中央。

iv. 如果按钮处于 的状态手动平移百度地图的时候,地图进行平移并且按钮变为 状态。

b) 获取当前所在位置与方向,并在百度地图上显示出来,如图中黑色箭头所示,箭头中心位置为定位结果,箭头方向为手机的朝向。

c) 实现简单摇一摇功能,当晃动手机的时候作出相应的响应。

 

实验过程

  1. 首先要申请百度的开发者密钥(申请密钥 Android SDK http://lbsyun.baidu.com/index.php?title=androidsdk/guide/key),申请地址:http://lbsyun.baidu.com/apiconsole/key

首先,在申请AK的表单中选择AndroidSDK,发现还要输入发布版SHA1以及报名这两个信息。

 

  其中,应用包名为build.gradle里的ApplicationId,并且保证这个ApplicationId与Manifest里的package字段名是一样的(如下图所示)。

                              Manifest 里的应用包名

 

                               build.gradle 里的应用包名

 

  发布版SHA1为了方便直接使用Android默认的debug.keystore里的SHA1,进入用户文件夹(Windows为C:\Users\username,Linux为/home/username,Mac为/Users/username)后,输入如下命令即可看到SHA1值(输入密钥库口令里直接回车)

证书指纹里的SHA1值为在申请应用AK的时候需要填写的。


点击确定后即可得到一个Android SDK的应用AK:

              成功申请应用 AK

 

  下载百度地图SDK的依赖库<BaiduLBS_AndroidSDK_Lib.zip>,按照百度地图SDK配置环境与发布 (配置环境及发布 Android SDK :http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject) 把依赖库放到相应的文件夹并添加到工程里,并按照HelloBaiduMap (Hello BaiduMap:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/hellobaidumap)中的步骤,在AndroidManifest.xml文件里添加权限以及应用AK。

 

  特别的,由于Android API 23以上需要动态申请权限,这里使用一个Github上的开源工具RxAndroid( https://github.com/ReactiveX/RxAndroid)进行处理,也可以自己根据Android官方的API进行或者其他的工具。首先需要在build.gradle中加入需要的依赖项:

  然后新建一个启动的Activity,在这个单独的Activity的onCreate方法里检查是否获取需要的权限,如果没有则直接退出程序,实现代码参考如下:

 

  本次实验主要涉及使用 android 手机不同的传感器,包括磁强计、加速度传感器等,使用 android 位置服务获得经纬度信息,使用百度地图基础 API 进行地图应用的开发。

  首先按照文档中的要求申请百度的开发者密钥,并正确申请 AK(应用包名为build.gradle里的ApplicationId,并且保证这个ApplicationId与Manifest里的 package 字段名是一样的):

 

  按照百度地图 SDK 配置环境与发布把依赖库放到相应的文件夹并添加到工程里,并按照 HelloBaiduMap 中的步骤,在 AndroidManifest.xml 文件里添加权限以及应用 AK:

这里进行 so 的配置时,在 app 工程路径下,新建 libs,并在 libs 目录下放入对应不同 CPU 架构的 so 文件。

  这样工程并不会自动加载 libs 下的 so,需在gradle 编译时,通过加入代码:jniLibs.srcDir 'libs' 来说明 so 的路径为该libs 路径。代码如下:

由于 Android API 23 以上需要动态申请权限,这里使用开源工具 RxAndroid进行处理(具体方法之前已叙述过,这里就不再赘述)。

 

接下来通过使用传感器来获取手机的方向信息和位置信息。

  手机的方向信息是通过地磁传感器和加速度传感器共同计算出来的,需要获取地磁传感器和加速度传感器的信息(调用手机大多数传感器首先需要获取传感器的管理器,传感器都需要由这个传感器管理器进行管理,包括注册传感器注销传感器等操作)。

  获取用户的经纬度信息需要使用位置管理器 LocationManager ,同时需要确认手机打开了位置服务。位置服务有一个位置的数据来源称为 provider ,可以分为 NETWORK_PROVIDER 和 GPS_PROVIDER ,其中 NETWORK_PROVIDER 使用基站和 Wi-Fi 信号来决定用户的位置,更新速度更快耗电量更少,但可能精确度较低,而 GPS_PROVIDER 使用 GPS 卫星进行定位,精度高但只能在室外使用,耗电量也更高。在使用过程中可以选择使用其中一个 provider,也可以两个provider 同时使用。在判断使用哪个 Provider 的时候,首先使用 isProviderEnabled 函数判断该 Provider 是否已经启用,从而选取一个合适的 Provider:

  在 Activity 在前台运行(onResume)的时候注册传感器,在离开前台(onPause)的时候取消注册。同时在注册传感器的时候,需要指定传感器的监听器,当传感器数据更新的时候,系统会回调监听器里的 onSensorChange 函数,可以在这里对传感器数据进行相应处理:

  手机的朝向是通过地磁传感器和加速度传感器共同计算出来,Android 提供了计算这个数值的 API,首先通过 getRotationMatrix 得到一个旋转矩阵,然后使用 getOrientation 得到手机的朝向:

  在使用加速度传感器的时候我们可以实现检测手机摇一摇的功能,这里我实现了通过摇一摇,弹出是否退出应用的对话框,选择是则退出应用:

  对于位置信息的更新,可以注册 LocationListener 监听位置信息的更新并作出相应的处理,使用 getLastKnownLocation 可以立刻获得一个位置坐标,如果之前有进行过定位操作,那么这个位置就是之前获取到的位置缓存,如果没有获得或位置,那么返回一个空对象:

 

  接下来实现地图的相关功能。首先,写好界面的 XML 布局文件。这里我们在布局文件里添加百度地图并需要设置一个 ToggleButton,并将 ToggleButton 背景设为@drawable/state,实现按钮背景图片的切换。

XML 文件如下:

背景 state.xml 文件如下:

 

  在 Activity 中初始化百度地图正常显示地图后,需要使用百度地图里MyLocationConfiguration 添加当前所在位置的箭头,并根据用户方向以及位置构造 MyLocationData ,相应设置箭头的方向与位置:

  LocationManager 返回的 Location 中的坐标系与百度地图的坐标系并不一样,需要进行坐标系的转换,最后 LatLng 得到的经纬度为百度地图坐标系下的经纬度:

  在地图中使显示手机朝向的箭头居中是使用 MapStatus 实现的(这里设置ToggleButton 为 cheaked 状态时显示手机朝向的箭头居中):

实现 BaiduMap 中的setOnMapTouchListener 函数来实现手动拖动地图平移之后按钮变化的功能:

  在 ToggleButton 点击事件、传感器监听器等位置再次实现获取当前位置信息的功能实现当按钮处于状态一时,如果 GPS 位置有更新,那么更新用户当前所在位置,并使得当前位置的箭头图标一直保持在屏幕中心;按钮处于状态二时,更新当前位置的箭头的时候不移动地图。

 

完成实验~

 

可能遇到的问题及解决方法

  在使用 locationManager.getLastKnownLocation(provider);时报错,出现Call requires permission which may be rejected by user. Code shouldexplicitly check to see if permission is available.的错误,不知道怎样解决。

解决方案:

  在查询了网上资料之后,了解到 Android 6.0 (SDK API level 23)新增了动态获取权限的特性。在获取用户信息时,需要检查用户是否授权,如果没有授权则需要向用户请求授权,对 Android 版本做兼容处理,对于 Android 6 及以上版本需要向用户请求授权,而低版本的则直接调用。

在加了以下语句后解决了此问题:

参考: http://majing.io/questions/226
    http://blog.5ibc.net/p/62176.html

 

实验截图

 

实现摇一摇功能:

 

其他总结

  Android 传感器框架让你访问许多类型的传感器。这些传感器的一些事基于硬件的,一些是基于软件的。基于硬件的传感器是内嵌到手机或者平板中的物理元件,它们通过直接测量指定的环境属性来得到它们的数据,例如加速度,磁场强度,或者角度变化。基于软件的传感器不是物理设备,尽管它们模仿基于硬件的传感器。基于软件的传感器从一个或更多基于硬件的传感器获取它们的数据,并且有时候被称为虚拟传感器或者合成传感器。线性加速度传感器和重力传感器是基于软件传感器的例子。表 1 总结了 Android 平台支持的传感器。很少 Android 设备有所有类型的传感器。例如,大部分手机和平板有一个加速计和磁场计,但是很少的设备拥有气压或者温度传感器。并且,一个设备可以拥有一个类型不止一个的传感器。例如,设备能有两个重力传感器,每个有不同的范围。

  大多数 Android 设备有内置的传感器,来测量运动,方向和各种环境条件。这些传感器能提供高精度和准确度的原始数据,如果你想监控设备三维运动或者位置,或者你想监控设备周围的环境变化,是非常有用的。例如,游戏可能跟踪设备重力传感器的数据,来推断复杂的用户首饰和动作,例如倾斜,震动,旋转,或者振幅。同样的,天气应用可能使用设备的温度传感器和湿度传感器的数据来计算和报告结露点,或者旅行应用可能使用磁场传感器和加速度传感器来报告一个指南针方位。

 

Android 平台支持三大类的传感器:

(1)位移传感器

这些传感器测量沿三个轴线测量加速度和旋转。这类包含加速度,重力传感器,陀螺仪,和矢量传感器。

(2)环境传感器

这些传感器测量各种环境参数,例如周围的空气温度和压力,光线,和湿度。这类包含气压,光线,和温度传感器。

(3)位置传感器

  这些传感器测量设备的物理位置。这类包含方向和磁力传感器。

  我们可以访问设备上可用的传感器,并通过使用 Android 传感器框架获取原始传感器数据。传感器框架提供了一些类和接口,来帮助你执行各种传感器相关的任务。例如,你能使用传感器框架做如下事情:

(1)确定什么传感器在设备上有效。

(2)确定当个传感器的功能,例如它的最大射程,厂商,电力需求,和分辨率。

(3)获取原始数据,并定义你获取传感器数据的最小速率。

(4)注册和注销传感器事件监听,来监听传感器改变。

 

(额~这段话好绕口~ 话粗理不粗嘛~)

 

源码下载

  源码下载点击这里~

 

1、本实验实验环境:

操作系统 Windows 10 

实验软件 Android Studio 2.2.1

虚拟设备:Nexus_5X

API:23

2、贴代码的时候由于插入代码框的大小问题,代码格式不太严整,望见谅~

posted @ 2017-02-24 13:29  yanglh6  阅读(2202)  评论(1编辑  收藏  举报