836
阿里云
技术社区[云栖]
Android定位功能
废话不多说,直接开始说说与实现Android定位有关的API吧。
这些API都在android.location包下,一共有三个接口和八个类。它们配合使用即可实现定位功能。
三个接口:
GpsStatus.Listener: 这是一个当GPS状态发生改变时,用来接收通知的接口。
GpsStatus.NmeaListener: 这是一个用来从GPS里接收Nmea-0183(为海用电子设备制定的标准格式)信息的接口。
LocationListener: 位置监听器,用于接收当位置信息发生改变时从LocationManager接收通知的接口。
八个类:
Address: 描述地址的类,比如:北京天安门
Criteria: 用于描述Location Provider标准的类,标准包括位置精度水平,电量消耗水平,是否获取海拔、方位信息,是否允许接收付费服务。
GeoCoder: 用于处理地理位置的编码。
GpsSatellite: 和GpsStatus联合使用,用于描述当前GPS卫星的状态。
GpsStatus: 和GpsStatus.Listener联合使用,用于描述当前GPS卫星的状态。
Location: 用于描述位置信息。
LocationManager: 通过此类获取和调用系统位置服务
LocationProvider: 用于描述Location Provider的抽象超类,一个LocationProvider应该能够周期性的报告当前设备的位置信息。
这里通过一个代码示例,演示一下如何实现定位。
首先,在AndroidManifest.xml清单文件里需要加入ACCESS_FINE_LOCATION权限
1
|
< uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" ></ uses-permission >
|
其次,实现代码如下:
003
|
import java.io.IOException;
|
004
|
import java.util.List;
|
006
|
import android.app.Activity;
|
007
|
import android.location.Address;
|
008
|
import android.location.Criteria;
|
009
|
import android.location.Geocoder;
|
010
|
import android.location.Location;
|
011
|
import android.location.LocationListener;
|
012
|
import android.location.LocationManager;
|
013
|
import android.os.Bundle;
|
014
|
import android.util.Log;
|
015
|
import android.widget.Toast;
|
017
|
public class MainActivity extends Activity
{
|
019
|
public void onCreate(Bundle
savedInstanceState) {
|
020
|
super .onCreate(savedInstanceState);
|
021
|
setContentView(R.layout.main);
|
023
|
//获取到LocationManager对象
|
024
|
LocationManager
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
|
026
|
Criteria
criteria = new Criteria();
|
028
|
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
|
030
|
criteria.setAltitudeRequired( false );
|
032
|
criteria.setBearingRequired( false );
|
034
|
criteria.setCostAllowed( true );
|
036
|
criteria.setPowerRequirement(Criteria.POWER_HIGH);
|
038
|
criteria.setSpeedRequired( false );
|
040
|
//根据设置的Criteria对象,获取最符合此标准的provider对象
|
041
|
String
currentProvider = locationManager.getBestProvider(criteria, true );
|
042
|
Log.d( "Location" , "currentProvider:
" +
currentProvider);
|
043
|
//根据当前provider对象获取最后一次位置信息
|
044
|
Location
currentLocation = locationManager.getLastKnownLocation(currentProvider);
|
045
|
//如果位置信息为null,则请求更新位置信息
|
046
|
if (currentLocation
== null ){
|
047
|
locationManager.requestLocationUpdates(currentProvider, 0 , 0 ,
locationListener);
|
049
|
//直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
|
052
|
currentLocation
= locationManager.getLastKnownLocation(currentProvider);
|
053
|
if (currentLocation
!= null ){
|
054
|
Log.d( "Location" , "Latitude:
" +
currentLocation.getLatitude());
|
055
|
Log.d( "Location" , "location:
" +
currentLocation.getLongitude());
|
058
|
Log.d( "Location" , "Latitude:
" + 0 );
|
059
|
Log.d( "Location" , "location:
" + 0 );
|
063
|
} catch (InterruptedException
e) {
|
064
|
Log.e( "Location" ,
e.getMessage());
|
069
|
Geocoder
geoCoder = new Geocoder( this );
|
071
|
int latitude
= ( int )
currentLocation.getLatitude();
|
072
|
int longitude
= ( int )
currentLocation.getLongitude();
|
073
|
List<Address>
list = geoCoder.getFromLocation(latitude, longitude, 2 );
|
074
|
for ( int i= 0 ;
i<list.size(); i++){
|
075
|
Address
address = list.get(i);
|
076
|
Toast.makeText(MainActivity. this ,
address.getCountryName() + address.getAdminArea() + address.getFeatureName(), Toast.LENGTH_LONG).show();
|
078
|
} catch (IOException
e) {
|
079
|
Toast.makeText(MainActivity. this ,e.getMessage(),
Toast.LENGTH_LONG).show();
|
085
|
private LocationListener
locationListener = new LocationListener(){
|
088
|
public void onLocationChanged(Location
location) {
|
089
|
Log.d( "Location" , "onLocationChanged" );
|
090
|
Log.d( "Location" , "onLocationChanged
Latitude" +
location.getLatitude());
|
091
|
Log.d( "Location" , "onLocationChanged
location" +
location.getLongitude());
|
096
|
public void onProviderDisabled(String
provider) {
|
097
|
Log.d( "Location" , "onProviderDisabled" );
|
102
|
public void onProviderEnabled(String
provider) {
|
103
|
Log.d( "Location" , "onProviderEnabled" );
|
108
|
public void onStatusChanged(String
provider, int status,
Bundle extras) {
|
109
|
Log.d( "Location" , "onStatusChanged" );
|
由于代码里的Criteria对象对位置精度要求并不高,所以一般会返回“network”作为provider,而基于network的定位往往会存在一定的位置偏差,这对于需要精确定位的应用程序来说,显然不合要求。这时,需要则需要用到基于GPS的定位方法了
在实现GPS定位前,先了解一下GPS的部分特性:
1. GPS定位需要依靠3颗或3颗以上的卫星。
2. GPS定位受环境影响较大,在晴朗的空地上,较容易搜索到卫星,而在室内通常是无法搜索到卫星的。
3. GPS定位需要使用GPS功能模块,而GPS功能模块的耗电量是巨大的。
在Android系统中,实现GPS定位的思路应该是:
1. 获取GPS的Location Provider。
2. 讲此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。
3. 创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)
001
|
public class MainActivity extends Activity
{
|
002
|
private LocationManager
locationManager;
|
003
|
private GpsStatus
gpsstatus;
|
005
|
public void onCreate(Bundle
savedInstanceState) {
|
006
|
super .onCreate(savedInstanceState);
|
007
|
setContentView(R.layout.main);
|
009
|
//获取到LocationManager对象
|
010
|
locationManager
= (LocationManager) getSystemService(LOCATION_SERVICE);
|
012
|
//根据设置的Criteria对象,获取最符合此标准的provider对象
|
013
|
String
currentProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER).getName();
|
015
|
//根据当前provider对象获取最后一次位置信息
|
016
|
Location
currentLocation = locationManager.getLastKnownLocation(currentProvider);
|
017
|
//如果位置信息为null,则请求更新位置信息
|
018
|
if (currentLocation
== null ){
|
019
|
locationManager.requestLocationUpdates(currentProvider, 0 , 0 ,
locationListener);
|
022
|
locationManager.addGpsStatusListener(gpsListener);
|
024
|
//直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
|
027
|
currentLocation
= locationManager.getLastKnownLocation(currentProvider);
|
028
|
if (currentLocation
!= null ){
|
029
|
Log.d( "Location" , "Latitude:
" +
currentLocation.getLatitude());
|
030
|
Log.d( "Location" , "location:
" +
currentLocation.getLongitude());
|
033
|
Log.d( "Location" , "Latitude:
" + 0 );
|
034
|
Log.d( "Location" , "location:
" + 0 );
|
038
|
} catch (InterruptedException
e) {
|
039
|
Log.e( "Location" ,
e.getMessage());
|
044
|
private GpsStatus.Listener
gpsListener = new GpsStatus.Listener(){
|
047
|
public void onGpsStatusChanged( int event)
{
|
049
|
gpsstatus=locationManager.getGpsStatus( null );
|
052
|
case GpsStatus.GPS_EVENT_FIRST_FIX:
|
055
|
case GpsStatus.GPS_EVENT_STARTED:
|
058
|
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
|
059
|
Toast.makeText(MainActivity. this , "GPS_EVENT_SATELLITE_STATUS" ,
Toast.LENGTH_SHORT).show();
|
060
|
Iterable<GpsSatellite>
allSatellites = gpsstatus.getSatellites();
|
061
|
Iterator<GpsSatellite>
it=allSatellites.iterator();
|
067
|
Toast.makeText(MainActivity. this , "Satellite
Count:" +
count, Toast.LENGTH_SHORT).show();
|
070
|
case GpsStatus.GPS_EVENT_STOPPED:
|
071
|
Log.d( "Location" , "GPS_EVENT_STOPPED" );
|
079
|
private LocationListener
locationListener = new LocationListener(){
|
082
|
public void onLocationChanged(Location
location) {
|
083
|
Log.d( "Location" , "onLocationChanged" );
|
088
|
public void onProviderDisabled(String
provider) {
|
089
|
Log.d( "Location" , "onProviderDisabled" );
|
094
|
public void onProviderEnabled(String
provider) {
|
095
|
Log.d( "Location" , "onProviderEnabled" );
|
100
|
public void onStatusChanged(String
provider, int status,
Bundle extras) {
|
101
|
Log.d( "Location" , "onStatusChanged" );
|
通过以上代码中的注释部分,可以清晰的知道Android定位功能里相关方法的具体含义。希望对大家有用。
另外,因为GPS的自身特性,此代码在室内几乎无法定位,所以建议再真正的实际项目里,至少使用network和GPS两种不同的Location Provider实现定位功能。
最后更新:2017-04-03 22:15:39