学习内容

Ø GPS的概念和用途

Ø LocationManager和LocationProvider

Ø LocationListener

能力目标

Ø 掌握GPS的概念和用途

Ø 掌握如何利用DDMS模拟定位

Ø 在Android中如何获取全部及指定的LocationProvider

Ø 掌握如何获取用户的位置

本章简介

现在的手机大多数都提供了GPS模块、通过GPS模块可以接收GPS信号,并可精确地指定目前所在的位置,如果将GPS定位功能应用到地图上,还可以实现导航、搜索公交、搜索驾车路线等实用且有趣功能。本章中我们先学习GPS的基本知识,然后通过具体的案例讲解Android环境中GPS开发的基本原理及步骤。学习过本章知识之后我们能够利用GPS进行简单的定位功能的开发。学习本章的重点是掌握LocationManager、LocationProvider与LocationListener等API的功能和用法,并可以通过它们来监听、获取GPS定位信息。

核心技能部分

9.1 GPS简介

全球定位系统GPS的全称是Global Positioning System,它是20世纪70年代由美国陆海空三军联合研制的新一代空间卫星导航定位系统。GPS的作用就是在全球范围内提供提供准确的定位、测量、和高精度的时间标准等功能。

GPS定位系统由三部分组成:GPS卫星组成的空间部分,若干地面站组成的控制部分和普通用户手机中的接收器。对于手机用户来说,手机就是GPS定位系统的接收器,也就是说GPS定位需要手机的硬件支持GPS功能。

GPS是一个中距离圆形轨道卫星导航系统,该系统包括太空中分布在倾角为55度的6个轨道上的24颗GPS卫星、地面上的一个主控站、3个数据注入站和5个监测站以及作为用户端的GPS接收器。最少只需要其中的3颗卫星,就能迅速确定用户端在地球上所处的位置及海拔坐标,所能接收到的卫星数越多,解码出来的数据就越精确。

GPS定位系统听上去专业、高深,是一门非常高深的技术,但对于Android应用开发的程序员来说,开发提供GPS功能的应用程序十分简单。就像Android为电话管理支持提供了TelephonyManager类、为音频管理支持提供了AudioManager类一样,Android为GPS提供了LocationManager类,通过LocationManager类及其他几个辅助类,我们可以非常方便地开发出功能强大的GPS应用。

9.2 获取LocationProvider

在Android中进行GPS开发,需要涉及LocationManager、LocationProvider、Location三个类。

LocationManager类的作用与TelephonyManager、AudioManager等服务类的作用相似,所有GPS定位相关的服务、对象都将由该对象来产生。与程序中获取TelephonyManager、AudioManager的方法相似 ,程序中获取LocationManager的实例是通过调用Context的getSystemService()方法来获取,如下代码所示:

LocationManager lm = getSystemService(Context.LOCATION_SERVICE);

一旦在程序中获得了LocationManager对象之后,接下来即可调用LocationManager的方法来获取GPS定位的相关服务和对象。

定位提供者LocationProvider是GPS定位组件的抽象表示,Android的定位信息就是由它提供的,即,通过LocationProvider类的方法可以获取定位组件的相关信息。

Location是位置信息的抽象类,它提供了大量用来获取定位信息的方法。

上面三个类就是Android GPS支持的三个核心API,使用它们获取GPS定位信息的通用步骤为:

(1) 获取系统的LocationManager对象。

(2) 使用LocationManager,通过指定LocationProvider来获取定位信息,定位信息由Location对象来表示。

(3) 从Location对象中获取定位信息。

示例9.1

获取LocationProvider。

通过前面的介绍可以看出,Android的定位信息由LocationProvider对象提供的,因此在开始编程之前,需要先获取LocationProvider对象。LocationManager提供了一个getAllProviders()方法,该方法可以用来获取系统所有可用的LocationProvider。

在布局文件中我们使用一个id为list的ListView组件,用来显示所有LocationProvider。

Activity类的代码如下:

public class GetAllProvidersActivity extends Activity {private ListView listView = null;private LocationManager manager = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.providers);listView = (ListView) findViewById(R.id.list);// 获取系统的LocationManager对象manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);// 获取系统所有的LocationProvider的名称List<String> providerNames = manager.getAllProviders();ArrayAdapter<String> adapter =new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,providerNames);// 使用ListView来显示所有可用的LocationProviderlistView.setAdapter(adapter);}}

运行程序,结果如下图9.1.1所示:

图9.1.1 系统所有LocationProvider

从图9.1.1可以看出,当前模拟器所有可用的LocationProvider有如下三个:

Ø network:由LocationManager.NETWORK_PROVIDER常量表示,它代表通过无线信号基站或Wi-fi网络获取定位信息的LocationProvider对象。

Ø passive:由LocationManager.PASSIVE_PROVIDER常量表示。

Ø gps:由LocationManager.GPS_PROVIDER常量表示,它代表通过GPS卫星获取定位信息的LocationProvider对象。

LocationManager类提供了访问定位服务的功能,该类提供了如下常用的方法。

Ø boolean  addGpsStatusListener(GpsStatus.Listener listener)

添加一个监听GPS状态的监听器。

Ø void  addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent)

设置当临近某指定位置(经度,纬度)和半径的位置时的警告信息。

Ø List<String>  getAllProviders()

获取所有的LocationProvider列表。

Ø String  getBestProvider(Criteria criteria, boolean enabledOnly)

根据指定条件返回最优的LocationProvider对象。

Ø GpsStatus  getGpsStatus(GpsStatus status)

获取GPS状态。

Ø Location  getLastKnownLocation(String provider)

根据LocationProvider获取最近一次已知的Location。

Ø LocationProvider  getProvider(String name)

根据名称来获取LocationProvider。

Ø List<String>  getProviders(Criteria criteria, boolean enabledOnly)

根据指定条件获取满足该条件的全部LocationProvider的名称。

Ø List<String>  getProviders(boolean enabledOnly)

获取所有可用的LocationProvider。

Ø boolean  isProviderEnabled(String provider)

判断指定名称的LocationProvider是否可用。

Ø void  removeGpsStatusListener(GpsStatus.Listener listener)

删除GPS状态监听器。

Ø void  removeProximityAlert(PendingIntent intent)

删除一个临近警告。

Ø void  requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent)

通过指定的LocationProvider周期性地获取定位信息,并通过intent启动相应的组件。

Ø void  requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)

通过指定的LocationProvider周期性地获取定位信息,并触发Listener所对应的触发器

例如,在示例9.1我们通过调用LocationManager的getAllProviders()方法获取所有LocationProvider时返回的是List<String>集合,集合元素即为LocationProvider的名称。我们还可以借助于LocationManager的getProvider(String name)方法,获取指定名称的LocationProvider对象。例如以下代码:

// 获取基于GPS的LocationProvider

LocationProvider  locprovider =

manager.getProvider(LocationManager.GPS_PROVIDER);

前面的程序调用LocationManager的getAllProviders()方法返回了系统所有可用的Location Provider,但大部分时候,应用程序可能希望得到符合指定条件的LocationProvider,这就需要借助于LocationManager的getBestProvider(Criteria criteria,boolean enabledOniy)方法来获取。

除了利用LocationManager类来获取LocationProvider外,我们还可以借助Criteria类来获取符合指定条件的LocationProvider。Criteria提供如下常用的方法来设置条件。

Ø void  setAccuracy(int accuracy)

设置对LocationProvider的精度要求。

Ø void  setAltitudeRequired(boolean altitudeRequired)

设置要求LocationProvider能提供高度信息。

Ø void  setBearingRequired(boolean bearingRequired)

设置要求LocationProvider能提供方向信息。

Ø void  setCostAllowed(boolean costAllowed)

设置要求LocationProvider是否免费。

Ø void  setPowerRequirement(int level)

设置要求LocationProvider的耗电量。

Ø void  setSpeedRequired(boolean speedRequired)

设置要求LocationProvider能提供速度信息。

示例9.2

根据Criteria类获取系统中免费的LocationProvider,并且该LocationProvider必须能提供高度信息、速度信息等。

本示例程序采用示例9.1的布局文件,我们重点来看一下Activity类的代码:

public class GetProvidersActivity extends Activity {private ListView listView = null;private LocationManager manager = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.providers);listView = (ListView) findViewById(R.id.list);// 获取系统的LocationManager对象manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);// 创建一个LocationProvider的过滤条件Criteria criteria = new Criteria();// 设置要求LocationProvider必须是免费的。criteria.setCostAllowed(false);// 设置要求LocationProvider能提供高度信息criteria.setAltitudeRequired(true);// 设置要求LocationProvider能提供方向信息criteria.setBearingRequired(true);// 获取系统所有复合条件的LocationProvider的名称List<String> providerNames = manager.getAllProviders();ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);// 使用ListView来显示所有可用的LocationProviderlistView.setAdapter(adapter);}}

运行该程序,即可在ListView中看到所有符合 Criteria条件的LocationProvider,程序运行结果和示例9.1相同。

9.3 GPS定位

9.3.1 使用DDMS模拟定位

Android模拟器本身并不能作为GPS接收器,因此无法得到GPS的定位信息,但为了方便程序员测试GPS应用,Android提供了DDMS工具来发送模拟的GPS信息。

启动Android模拟器之后,然后打开Eclipse的DDMS透视图下的Emulator Control面板即可向Android模拟器发送GPS定位信息,如图9.1.2所示。

图9.1.2 Emulator Control面板

9.3.2 获取用户的位置

当我们可以获取到LocationProvider的时候,就可以通过其提供的位置组件获取到设备此时的Position位置信息,到这里,我们就实现了通过手机自带的GPS设备获取当前位置信息的一整套简单流程,下面我们通过一个示例来演示获取用户信息的简单应用。

示例9.3

获取用户当前的地理位置,利用DDMS模拟器模拟用户当前的位置数据。

在布局文件中提供一个按钮,当用户单击这个按钮时程序能通过LocationProvider周期性地获取定位信息,并触发Listener所指定的LocationListener类型的触发器。Android类及自定义LocationListener的详细代码如下:

public class UserLocationActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.userlocation);Button button1 = (Button) findViewById(R.id.btn1);button1.setOnClickListener(new OnClickListener() {public void onClick(View v) {//通过名字来得到指定的系统级的服务LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,locationListener);   ------------------①}});}LocationListener locationListener = new LocationListener() {public void onStatusChanged(String provider, int status, Bundle extras) {}public void onProviderEnabled(String provider) {}public void onProviderDisabled(String provider) {}public void onLocationChanged(Location location) {System.out.println(location.getLatitude());System.out.println(location.getLongitude());}}

上面的程序中粗体字代码用于从Location中获取经度、纬度定位信息。程序中编号为处的代码通过LocationManager设置了一个监听器,该监听器负责每隔1秒向LocationProvider请求一次定位信息,当用户的定位信息发生改变时,系统会在LogCat下输出用户的定位信息。程序中用到的requestLocationUpdates()方法的原型如下:

void LocationManager.requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)

该方法通过指定的LocationProvider周期性地获取定位信息,并出发listener所对应的触发器。

定位提供者LocationProvider对象就是GPS定位组件的抽象表示,通过LocationProvider可以获取该定位组件的相关信息。LocationProvider提供了如下常用方法。

Ø abstract int  getAccuracy()

返回LocationProvider的精度。

Ø String  getName()

返回LocationProvider的名称。

Ø abstract int  getPowerRequirement()

获取LocationProvider的电源需求。

Ø abstract boolean  hasMonetaryCost()

Ø 返回该LocationProvider是收费的还是免费的

Ø boolean  meetsCriteria(Criteria criteria)

Ø 判断该LocationProvider是否满足Criteria条件。

Ø abstract boolean  requiresCell()

判断该LocationProvider是否需要访问网络基站。

Ø abstract boolean  requiresNetwork()

判断该LocationProvider是否需要网络数据。

Ø abstract boolean  requiresSatellite()

判断该LocationProvider是否需要访问基于卫星的定位系统。

Ø abstract boolean  supportsAltitude()

判断该LocationProvider是否支持高度信息。

Ø abstract boolean  supportsBearing()

判断该LocationProvider是否支持方向信息。

Ø abstract boolean  supportsSpeed()

判断该LocationProvider是否支持速度信息。

onLocationChanged 方法的参数的类型Location代表位置信息的抽象类,该类是GPS技术的一个很重要的类,它提供了如下重要的方法:

Ø boolean  hasAccuracy()

获取定位信息的精度。

Ø double  getAltitude()

获取定位信息的高度。

Ø float  getBearing()

获取定位信息的方向。

Ø double  getLatitude()

获取定位信息的纬度。

Ø double  getLongitude()

获取定位信息的经度。

Ø String  getProvider()

获取提供该定位信息的LocationProvider。

Ø float  getSpeed()

获取定位信息的速度。

Ø boolean  hasAccuracy()

判断该定位信息是否有精度信息。

Ø boolean  hasAltitude()

判断该定位信息是否有高度信息。

Ø boolean  hasBearing()

判断该定位信息是否有方向信息。

Ø boolean  hasSpeed()

判断该定位信息是否有速度信息。

该程序需要有访问GPS信号的权限,因此需要在AndroidManifest.xml文件中增加如下授权代码片段:

<!—授权获取定位信息-->

<use-permission android:name=’”android.permission.ACCESS_FINE_LOCATION”/>

首先运行该程序,然后单击图9.2中的【Send】按钮,在Eclipse的LogCat下我们会看到用户的位置信息,如下图9.1.3所示。

图9.1.3 用户位置信息

如果把该程序与Google Map结合,让该程序根据GPS提供的信息实时地显示用户在地图上的位置,即可开发出GPS导航系统。

9.3.3 指定区域临近警告

通过上面的示例,我们已经可以获取到设备所在的位置信息,但是,简单的经纬度信息对我们来说依然用处不大,实际生活中,我们更多的是通过GPS功能寻找我们的目的地,这里的目的地其实也是一个经纬度代表的位置信息,当我们靠近此位置达到一定的半径范围时,会有相应的提示通知我们,例如很多车辆上的GPS导航系统中会内置道路上的摄像头位置,当到此区域时提醒司机注意行驶速度等,这里就需要我们能判断出用户与指定位置之间的距离关系,当用户临近此指定位置时给出警告,这也就是我们这节要讲的位置临近警告。

所谓临近警告指的是当用户手机不断靠近指定固定点,当与该固定点的距离小于指定范围时,系统可以触发相应的处理。Android中,LocationManager类提供了一个名称为addProximityAlert(double latitude,double longitude,float radius,long expiration,PendingIntent intent)方法,该方法用于添加一个临近警告,它参数的说明如下。

Ø longitude:指定固定点的经度。

Ø latitude:指定固定点的纬度。

Ø radius:该参数指定一个半径长度。

Ø expiration:该参数指定经过多少毫秒后该临近警告就会过期失效。-1指定永不过期。

Ø intent:该参数指定临近该固定点时触发该intent对应的组件。

示例9.4

指定区域临近警告。

本示例程序演示了如何检测手机是否进入郑州二七广场。当程序启动后,程序就会添加一个临近警告,当用户临近郑州二七广场所在纬度、经度时,系统会以文本的形式在屏幕上显示提示信息。

本程序的实现思想是借助一个Intent接收器以经纬度为圆心以指定值为半径划定一个区域,当设备出入该区域时,发出提醒信息。

本示例的布局文件比较简单,在布局文件里面只提供了一个TextView,用来显示当用户进出二七广场时的提示信息。我们来重点看一下Activity类的代码:

public class ProximityActivity extends Activity {private TextView textView = null;private LocationManager manager = null;   // 定位服务管理器实例@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.proximity);textView = (TextView) findViewById(R.id.textView1);// 通过getSystemService方法获得LocationManager实例manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);double longitude = 113.66632841527462;double latitude = 34.752014421190424;float radius = 2500;// 定义半径(2.5公里)// 定义IntentIntent intent = new Intent(this, ProximityAlertReciever.class);// 将Intent包装成PendingIntentPendingIntent pendingIntent = PendingIntent.getBroadcast(this, -1, intent, 0);// 添加临近警告manager.addProximityAlert(latitude, longitude, radius, -1, pendingIntent);}class ProximityAlertReciever extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 获取是否为进入指定区域boolean isEnter = intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);if (isEnter) {textView.setText("您已经进入郑州二七广场");// 显示提示信息} else {textView.setText("您已经离开郑州二七广场");// 显示提示信息}}}}

在上面的Activity类,我们通过自定义的广播接收者,当广播到来时,根据不同的情况在屏幕上来显示用户进出二七区时的相应提示信息。

注意:不要忘记在功能清单文件中对广播进行注册。

打开DDMS的Emulator Control面板,在其中输入指定的纬度、经度信息,我们可以看到下图9.1.4、9.1.5所示的效果。

图9.1.4 进入指定地点

图9.1.5 离开指定地点

本示例可以和下一章中将要讲到的Google Map一起使用,完成许多非常有特色的功能。

任务实训部分 

1:自定义实现一个位置记录器

训练技能点

如何获取用户位置

需求说明

在本节中我们学习了如何获取用户位置,假设我们在做一个服务器(比如一个网站),当用户移动时,随时将用户的位置信息提交到服务器端。这个在现实生活中是有很大应用的,比如父母可利用它来临近孩子玩耍的地点,避免孩子丢失。

根据此需求,实现网站和手机端的应用。

2:查找最合适的LocationProvider

训练技能点

利用Criteria查找满足指定条件的LocationProvider

需求说明

在实际的应用中,一般情况下我们需要的不是所有的LocationProvider,而是满足指定条件的LocationProvider,比如免费、需要网络数据、支持高度信息等。本示例要求大家完成查找满足低电耗、支持高度、免费的LocationProvider。

实现思路

核心代码如下:Criteria criteria = new Criteria();criteria.setAccuracy(Criteria.ACCURACY_FINE);criteria.setPowerRequirement(Criteria.POWER_LOW);criteria.setAltitudeRequired(false);criteria.setSpeedRequired(false);criteria.setCostAllowed(false);//通过名字来得到指定的系统级的服务LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);String provider = manager.getBestProvider(criteria, false);System.out.println(provider);

巩固练习

一、简答题

1. 简要描述GPS是什么以及它的功能。

2. 简述在Android中获取GPS定位信息的步骤。

二、上机练习

编写一个小型的动画,动画界面中提供一个小车(用图片表示),一条带有障碍物的道路。当汽车在道路上行走,接近道路上的路障时,汽车自动停止或绕开。

android项目入门实践之GPS用户定位相关推荐

  1. 基于qiankun搭建ng-alain15微前端项目入门实践

    基础环境 实践日期:2023-02-22 ng versionAngular CLI: 15.1.6 Node: 18.14.2 Package Manager: npm 9.5.0 OS: win3 ...

  2. Android附近基站+Wifi+IP+GPS多渠道定位方案

    wifi定位wiki:https://developers.google.com/maps/documentation/geolocation/intro 前言: 在移动客户端的开发中,地理位置定位是 ...

  3. 微信公众号H5项目中用高德地图实现用户定位(vue)

    遇到的问题:用高德官网的方法去定位时发现,ios可以在http的网址定位,而安卓手机只能在https的网址定位,这个也是很奇葩,查了官网文档说,是因为浏览器禁止了非安全域的定位请求.但是我们的站点就是 ...

  4. Android提升篇系列:Android项目代码优化实践

    Android开发中,不同的开发团队,不同的开发人员,在实际编码中会有一些不同的地方. 但是,具有一定的更普适性的编码习惯,无疑还是相当重要的.本文主要罗列项目中常见的一些编码片段,并给出相关建议. ...

  5. Android自定义控件入门实践之雷达扫描控件

    以前因为工作的关系,对于自定义控件用的少之又少,无非就是把几个控件放置到ViewGroup内部,然后提供开放方法,就成了一个所谓的自定义控件,但是这种小伎俩太简单,面试的时候这点东西根本Hold不住场 ...

  6. 基于qiankun搭建ng-alain15微前端项目示例实践

    基础环境 实践日期:2023-03-04 ng versionAngular CLI: 15.2.1 Node: 18.14.2 Package Manager: npm 9.5.0 OS: win3 ...

  7. Android项目集成高德地图定位功能

    1.在Project的build.gradle文件中配置repositories,添加maven或jcenter仓库地址 Android Studio默认会在Project的build.gradle为 ...

  8. Android开发--用户定位服务--UserLocation

    用户定位介绍: User Location的作用: 1.获取用户的位置 2.追踪用户的移动 User Location的关键API 1.Location Manager:用于管理Android的用户定 ...

  9. android hook底层代码_Java-Hook技术-入门实践(反射、动态代理)-Hook拦截通知(当前App/Context)...

    老样子,上一篇MonkeyLei:Java-Hook技术-入门实践+反射.动态代理.热修复再看看 我们Hook学习了一下,一个是Java本地Main的实践练习. 一个是Android的监听事件的Hoo ...

最新文章

  1. linux mysql 数据目录迁移后不生效_Linux中更改转移mysql数据库目录的步骤
  2. C# list集合 重复元素 索引_C#学习笔记12--集合/索引器/扩展
  3. 如何在原先的jqgrid中填充新的数据_如何提升NX工程师的逆向能力与速度
  4. 人工智能修复古董纪录片,还原1920年的北京城生活
  5. [Java] 蓝桥杯ALGO-42 算法训练 送分啦
  6. Svn分支管理的使用(三)
  7. 【命令行】CMD/BAT文件执行时中文乱码的解决方法
  8. 雅马哈推出可以播放黑胶唱片和流行音乐的无线唱盘
  9. php 汉字转拼音 [包含20902个基本汉字+5059生僻字]
  10. html调用如何使用jeecms库,JEECMS标签使用实例教程-序
  11. win7如何修改html图标,Win7如何更改软件图标?Win7更改软件图标的方法
  12. 正负图表,让数据展示更炫酷
  13. python怎么将删的代码恢复_找回丢失的Python代码--如果代码还驻留在内存中
  14. 浅析疯狂动物城的制作流程
  15. 520探讨一下如何给geek男友选礼物?(超实用)
  16. 2021-12-3 温故而知新-JavaScript隐式转换
  17. rc命令 linux,Ubuntu Update-rc.d命令详细介绍
  18. Android自带组件之Gallery 实现3D画廊效果
  19. 【SwinTransformer源码阅读一】build_loader部分代码
  20. 网站推广-----100个基本推广方法

热门文章

  1. VUE3 获取元素高度
  2. CodeMix使用教程:重构
  3. Unity项目总结 模型制作 场景搭建
  4. Java创建遍历二叉树(递归)并求树高及叶节点个数(代码全)
  5. 关联规则——Apriori算法
  6. 大数据面试题——数据仓库
  7. 二维数组作为函数参数问题
  8. BeanCopier工具类
  9. android 定时器 误差,【万能定时器】万能定时器安卓版下载-优基地
  10. 电子设计大赛作品_赛事“暨”忆录|重大比赛介绍第二期——电子设计大赛省赛比赛介绍...