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