废话不多说,直接开始说说与实现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); |
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 ); |
041 |
String
currentProvider = locationManager.getBestProvider(criteria, true ); |
042 |
Log.d( "Location" , "currentProvider:
" +
currentProvider); |
044 |
Location
currentLocation = locationManager.getLastKnownLocation(currentProvider); |
046 |
if (currentLocation
== null ){ |
047 |
locationManager.requestLocationUpdates(currentProvider, 0 , 0 ,
locationListener); |
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); |
010 |
locationManager
= (LocationManager) getSystemService(LOCATION_SERVICE); |
013 |
String
currentProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER).getName(); |
016 |
Location
currentLocation = locationManager.getLastKnownLocation(currentProvider); |
018 |
if (currentLocation
== null ){ |
019 |
locationManager.requestLocationUpdates(currentProvider, 0 , 0 ,
locationListener); |
022 |
locationManager.addGpsStatusListener(gpsListener); |
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实现定位功能。