入門資料參考:
How accurate is Android GPS? Part 1: Understanding Location DataHow accurate is Android GPS? Part 2 – Consuming real-time locations
Google Developer docs – Location Strategies
Android blog – Deep dive into location
GPS Testing Tool (open source)
HTML5 Geolocation API – How accurate is it, really?
測試demo工程:
GpsActivty.java
public class GpsActivity extends Activity { private EditText editText; private TextView logText; private LocationManager lm; private static final String TAG="GpsActivity"; @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); lm.removeUpdates(locationListener); } private void setLog(String txt){ printTime(); setLogInfo(txt); } private void setLogInfo(String txt){ logText.setText(txt+"\n"+"--------------------\n"+logText.getText()); } private void printTime(){ Calendar ca = Calendar.getInstance(); int year = ca.get(Calendar.YEAR);//擷取年份 int month=ca.get(Calendar.MONTH);//擷取月份 int day=ca.get(Calendar.DATE);//擷取日 int minute=ca.get(Calendar.MINUTE);//分 int hour=ca.get(Calendar.HOUR);//小時 int second=ca.get(Calendar.SECOND);//秒 int WeekOfYear = ca.get(Calendar.DAY_OF_WEEK); setLogInfo("當前日期:" + year +"年"+ month +"月"+ day + "日"); setLogInfo(">>>" + hour +"時"+ minute +"分"+ second +"秒"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gps_demo); editText=(EditText)findViewById(R.id.editText); logText=(TextView) this.findViewById(R.id.logText); lm=(LocationManager)getSystemService(Context.LOCATION_SERVICE); //判斷GPS是否正常啟動 if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){ Toast.makeText(this, "請開啟GPS導航...", Toast.LENGTH_SHORT).show(); setLog("請開啟GPS導航..."); //返回開啟GPS導航設定介面 Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivityForResult(intent,0); return; } //為擷取地理位置資訊時設定查詢條件 String bestProvider = lm.getBestProvider(getCriteria(), true); //擷取位置資訊 //如果不設定查詢要求,getLastKnownLocation方法傳人的參數為LocationManager.GPS_PROVIDER Location location= lm.getLastKnownLocation(bestProvider); updateView(location); //監聽狀態 lm.addGpsStatusListener(listener); //綁定監聽,有4個參數 //參數1,裝置:有GPS_PROVIDER和NETWORK_PROVIDER兩種 //參數2,位置資訊更新周期,單位毫秒 //參數3,位置變化最小距離:當位置距離變化超過此值時,將更新位置資訊 //參數4,監聽 //備忘:參數2和3,如果參數3不為0,則以參數3為準;參數3為0,則通過時間來定時更新;兩者為0,則隨時重新整理 // 1秒更新一次,或最小位移變化超過1米更新一次; //注意:此處更新準確度非常低,推薦在service裡面啟動一個Thread,在run中sleep(10000);然後執行handler.sendMessage(),更新位置 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, locationListener); } //位置監聽 private LocationListener locationListener=new LocationListener() { /** * 位置資訊變化時觸發 */ public void onLocationChanged(Location location) { updateView(location); Log.i(TAG, "時間:"+location.getTime()); Log.i(TAG, "經度:"+location.getLongitude()); Log.i(TAG, "緯度:"+location.getLatitude()); Log.i(TAG, "海拔:"+location.getAltitude()); setLog( "時間:"+location.getTime()); setLog( "經度:"+location.getLongitude()); setLog( "緯度:"+location.getLatitude()); setLog( "海拔:"+location.getAltitude()); } /** * GPS狀態變化時觸發 */ public void onStatusChanged(String provider, int status, Bundle extras) { switch (status) { //GPS狀態為可見時 case LocationProvider.AVAILABLE: Log.i(TAG, "當前GPS狀態為可見狀態"); setLog("當前GPS狀態為可見狀態"); break; //GPS狀態為服務區外時 case LocationProvider.OUT_OF_SERVICE: Log.i(TAG, "當前GPS狀態為服務區外狀態"); setLog("當前GPS狀態為服務區外狀態"); break; //GPS狀態為暫停服務時 case LocationProvider.TEMPORARILY_UNAVAILABLE: Log.i(TAG, "當前GPS狀態為暫停服務狀態"); setLog("當前GPS狀態為暫停服務狀態"); break; } } /** * GPS開啟時觸發 */ public void onProviderEnabled(String provider) { Location location=lm.getLastKnownLocation(provider); updateView(location); } /** * GPS禁用時觸發 */ public void onProviderDisabled(String provider) { updateView(null); } }; //狀態監聽 GpsStatus.Listener listener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { switch (event) { //第一次定位 case GpsStatus.GPS_EVENT_FIRST_FIX: Log.i(TAG, "第一次定位"); setLog("第一次定位"); break; //衛星狀態改變 case GpsStatus.GPS_EVENT_SATELLITE_STATUS: Log.i(TAG, "衛星狀態改變"); setLog("衛星狀態改變"); //擷取目前狀態 GpsStatus gpsStatus=lm.getGpsStatus(null); //擷取衛星顆數的預設最大值 int maxSatellites = gpsStatus.getMaxSatellites(); //建立一個迭代器儲存所有衛星 Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator(); int count = 0; while (iters.hasNext() && count <= maxSatellites) { GpsSatellite s = iters.next(); count++; } System.out.println("搜尋到:"+count+"顆衛星"); setLog("搜尋到:"+count+"顆衛星"); break; //定位啟動 case GpsStatus.GPS_EVENT_STARTED: Log.i(TAG, "定位啟動"); setLog("定位啟動"); break; //定位結束 case GpsStatus.GPS_EVENT_STOPPED: Log.i(TAG, "定位結束"); setLog("定位結束"); break; } }; }; /** * 即時更新常值內容 * * @param location */ private void updateView(Location location){ if(location!=null){ editText.setText("裝置位置資訊\n\n經度:"); editText.append(String.valueOf(location.getLongitude())); editText.append("\n緯度:"); editText.append(String.valueOf(location.getLatitude())); }else{ //清空EditText對象 editText.getEditableText().clear(); } } /** * 返回查詢條件 * @return */ private Criteria getCriteria(){ Criteria criteria=new Criteria(); //設定定位精確度 Criteria.ACCURACY_COARSE比較粗略,Criteria.ACCURACY_FINE則比較精細 criteria.setAccuracy(Criteria.ACCURACY_FINE); //設定是否要求速度 criteria.setSpeedRequired(false); // 設定是否允許電訊廠商收費 criteria.setCostAllowed(false); //設定是否需要方位資訊 criteria.setBearingRequired(false); //設定是否需要海拔資訊 criteria.setAltitudeRequired(false); // 設定對電源的需求 criteria.setPowerRequirement(Criteria.POWER_LOW); return criteria; }}
然後在layout目錄建立 gps_demo.xml
<?xml version="1.0" encoding="utf-8"?> <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" ><LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:cursorVisible="false" android:editable="false" android:id="@+id/editText"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:minHeight="300dp" android:id="@+id/logText"/></LinearLayout> </ScrollView>
最後在AndroidManifest.xml裡添加需要的許可權
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
手機啟動並執行
注意事項:
1、室內是無法檢測到GPS訊號的,如果你獲得了經緯度,那也是最後一次手機緩衝的GPS記錄。
2、你獲得gps位移量大的問題,請參照 關於GPS位移的基礎知識