轉載請注明出處:http://www.cnblogs.com/Joanna-Yan/p/5715879.html
GPS定位系統由三部分組成,即由GPS衛星組成的空間部分,若干地面組成的控制部分和普通用戶手中的接收機這三部分。對於手機用戶來說,手機就是GPS定位系統的接收機,也就是說GPS定位需要手機的硬件支持GPS功能。
一、核心API
Android為GPS功能支持專門提供了一個LocationManager類,
LocationManager lm=(LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
其常用方法如下:
> 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(provider): 判斷指定名稱的LocationProvider是否可用
> void removeGpsStatusListener(GpsStatus.Listener listener): 刪除Gps狀態監聽器
> void removeProximityAlert(PendingIntent intent): 刪除一個臨近警告
> void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent): 通過指定的LoactionProvider周期性地獲取定位信息,並通過intent啟動相應的組件。
> void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener): 通過指定的LocationProvider周期性地獲取定位信息,並觸發listener所對應的觸發器。
LocationProvider(定位提供者),LocationProvider對象就是定位組件的抽象表示,通過LocationProvider可以獲取該定位組件的相關信息。常用方法如下:
> int getAccuracy(): 返回該LocationProvider的精度
> String getName(): 返回該LocationProvider的名稱
> int getPowerRequirement(): 獲取該LocationProvider的電源需求
> boolean hasMonetaryCost(): 獲取該LocationProvider是收費的還是免費的
> boolean meetsCriteria(Criteria criteria) : 判斷該LocationProvider是否滿足Criteria條件
> boolean requiresCell(): 判斷該LocationProvider是否需要訪問網絡基站
> boolean requiresNetwork(): 判斷該LocationProvider是否需要網絡數據
> boolean requiresSatellite(): 判斷該LocationProvider是否需要訪問基於衛星的定位系統
> boolean supportsAltitude(): 判斷該LocationProvider是否支持高度信息
> boolean supportsBearing(): 判斷該LocationProvider是否支持方向信息
> boolean supportsSpeed(): 判斷該LocationProvider是否支持速度信息
Location,一個代表位置信息的抽象類,提供如下方法來獲取定位信息
> float getAccuracy(): 獲取定位信息的精度
> double getAltitude(): 獲取定位信息的高度
> float getBearing(): 獲取定位信息的方向
> getLatitude(): 獲取定位信息的緯度
> getLongitude(): 獲取定位信息的經度
> getProvider(): 獲取提供該定位信息的LocationProvider
> getSpeed(): 獲取定位信息的速度
> hasAccuracy(): 判斷該定位信息是否有精度信息
> hasAltitude(): 判斷該定位信息是否有高度信息
> hasBearing(): 判斷該定位信息是否有方向信息
> hasSpeed(): 判斷該定位信息是否有速度信息
這三個API是Android GPS支持的三個核心API,用它們來獲取GPS定位信息的通過步驟為:
(1) 獲取系統的LocationManager對象
(2) 使用LocationManager,通過指定LocationProvider來獲取定位信息,定位信息由Location對象來表示
(3) 從Location中獲取定位信息
二、獲取LocationProvider
Android的定位信息由LocationProvider對象來提供,該對象代表一個抽象的定位組件。在編程之前需要先獲取LocationProvider對象。
1. 示例:獲取所有可用的LocationProvider
ListView providers;
LocationManager lm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_providers);
providers=(ListView) findViewById(R.id.providers);
lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> providerNames=lm.getAllProviders();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);
providers.setAdapter(adapter);
}
}
如圖可看出當前模擬器所有可用的LocationProvider有三個:
> passive: 由LocationManager.PASSIVE_PROVIDER常量表示
> gps: 由LocationManager.GPS_PROVIDER常量表示,代表通過GPS獲取定位信息的LocationProvider對象
> network: 由LocationManager.NETWORK_PROVIDER常量表示,代表通過移動通信網絡獲取定位信息的LocationProvider對象
2. 通過名稱獲得指定LocationProvider
//獲得基於GPS的LocationProvider LocationProvider gpsProvider=lm.getProvider(LocationManager.GPS_PROVIDER);
3. 根據Criteria獲取LocationProvider
LocationManager的getBestProvider(Criteria criteria,boolean enabledOnly)用來得到符合指定條件的LocationProvider。Criteria代表了一個過濾條件,提供如下常用方法來設置:
> setAccuracy(int accuracy): 設置對LocationProvider的精度要求
> setAltitudeRequired(boolean altitudeRequired): 設置要求LocationProvider能提供高度信息
> setBearingRequired(boolean bearingRequired): 設置要求LocationProvider能提供方向信息
> setCostAllowed(boolean costAllowed): 設置要求LocationProvider是否免費
> setPowerRequirement(int level): 設置要求LocationProvider的耗電量
> setSpeedRequired(boolean speedRequired): 設置要求LocationProvider能提供速度信息
示例:獲取系統中免費的、能提供高度信息、速度信息的LocationProvider
ListView providers;
LocationManager lm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_providers);
providers=(ListView) findViewById(R.id.providers);
lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria cri=new Criteria();
cri.setCostAllowed(false);
cri.setAltitudeRequired(true);
cri.setBearingRequired(true);
List<String> providerNames=lm.getAllProviders();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);
providers.setAdapter(adapter);
}
}
public class AllProvidersActivity extends Activity { ListView providers; LocationManager lm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_all_providers); providers=(ListView) findViewById(R.id.providers); lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria cri=new Criteria(); cri.setCostAllowed(false); cri.setAltitudeRequired(true); cri.setBearingRequired(true); List<String> providerNames=lm.getAllProviders(); ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames); providers.setAdapter(adapter); } }
三、獲取定位信息
示例:通過手機實時獲取定位信息,包括用戶所在的經度、緯度、高度、方向、移動速度等
LocationManager lm;
EditText show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
show=(EditText) findViewById(R.id.show);
lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
//從GPS獲取最近的定位信息
Location location=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Log.i("LocationActivity", "location="+location);
updateView(location);
//每3秒獲取一次GPS的定位信息
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8, new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
// 當GPS LocationProvider可用時,更新位置
updateView(lm.getLastKnownLocation(provider));
}
@Override
public void onProviderDisabled(String provider) {
updateView(lm.getLastKnownLocation(null));
}
@Override
public void onLocationChanged(Location location) {
//GPS定位信息發生改變時,更新位置
updateView(location);
}
});
}
public void updateView(Location newLocation){
if(newLocation!=null){
StringBuilder sb=new StringBuilder();
sb.append("實時的位置信息:\n");
sb.append("經度:");
sb.append(newLocation.getLongitude());
sb.append("\n緯度:");
sb.append(newLocation.getLatitude());
sb.append("\n高度:");
sb.append(newLocation.getAltitude());
sb.append("\n速度:");
sb.append(newLocation.getSpeed());
sb.append("\n方向:");
sb.append(newLocation.getBearing());
show.setText(sb.toString());
}else{
show.setText("");
}
}
}
public class LocationActivity extends Activity { LocationManager lm; EditText show; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_location); show=(EditText) findViewById(R.id.show); lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE); //從GPS獲取最近的定位信息 Location location=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); Log.i("LocationActivity", "location="+location); updateView(location); //每3秒獲取一次GPS的定位信息 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8, new LocationListener() { @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { // 當GPS LocationProvider可用時,更新位置 updateView(lm.getLastKnownLocation(provider)); } @Override public void onProviderDisabled(String provider) { updateView(lm.getLastKnownLocation(null)); } @Override public void onLocationChanged(Location location) { //GPS定位信息發生改變時,更新位置 updateView(location); } }); } public void updateView(Location newLocation){ if(newLocation!=null){ StringBuilder sb=new StringBuilder(); sb.append("實時的位置信息:\n"); sb.append("經度:"); sb.append(newLocation.getLongitude()); sb.append("\n緯度:"); sb.append(newLocation.getLatitude()); sb.append("\n高度:"); sb.append(newLocation.getAltitude()); sb.append("\n速度:"); sb.append(newLocation.getSpeed()); sb.append("\n方向:"); sb.append(newLocation.getBearing()); show.setText(sb.toString()); }else{ show.setText(""); } } }
個人總結:
1. 因為GPS信號偶爾會不好,所以僅使用gps的時候,絕大多數情況下會出現getLastKnowLocation為null,需要在系統的定位模式中,要允許使用wifi和network定位;這樣即使gps定位返回null,network也能得到粗略的位置信息。
2. getLastKnownLocation經常取不到東西的,使用百度定位SDK吧,比較靠譜。
3. getLastKnowLocation不是一次就能定位成功,必須要多次定位。
4. 要在空曠無遮擋物的地方。
四、臨近警告
LocationManager提供一個方法addProximityAlert(double latitude,double longitude,float radius, long expiration, PendingIntent intent)用於添加一個臨近警告。當用戶手機不斷臨近指定固定點時,當與該固定點的距離小於指定范圍時,系統可以觸發相應的處理。
示例:
LocationManager lm;
double longitude=113.39;
double latitude=23.13;
float radius=5000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_proximity_test);
lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
Intent intent=new Intent(this,ProximityAlertReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(this, -1, intent, 0);
//第四個參數指定經過多少毫秒后該臨近警告就會過期失效,-1指定永不過期
lm.addProximityAlert(latitude, longitude, radius, -1, pi);
}
public class ProximityAlertReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
boolean isEnter=intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
if(isEnter){
Toast.makeText(context, "你已進入禁止區域", 0).show();
}else{
Toast.makeText(context, "你離開禁止區域", 0).show();
}
}
}
}
public class ProximityTestActivity extends Activity { LocationManager lm; double longitude=113.39; double latitude=23.13; float radius=5000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_proximity_test); lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE); Intent intent=new Intent(this,ProximityAlertReceiver.class); PendingIntent pi=PendingIntent.getBroadcast(this, -1, intent, 0); //第四個參數指定經過多少毫秒后該臨近警告就會過期失效,-1指定永不過期 lm.addProximityAlert(latitude, longitude, radius, -1, pi); } public class ProximityAlertReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { boolean isEnter=intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false); if(isEnter){ Toast.makeText(context, "你已進入禁止區域", 0).show(); }else{ Toast.makeText(context, "你離開禁止區域", 0).show(); } } }