android開發之GPS定位詳解

一、LocationManager

 

LocationMangager,位置管理器。要想操作定位相關設備,必須先定義個LocationManager。我們可以通過如下代碼創建LocationManger對象。

 

[java] view plaincopyprint?

LocationManger locationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);   

 

 

二、LocationListener

 

LocationListener,位置監聽,監聽位置變化,監聽設備開關與狀態。

 

[java] view plaincopyprint?

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());   

        }  

          

        /** 

         * GPS狀態變化時觸發 

         */  

        public void onStatusChanged(String provider, int status, Bundle extras) {  

            switch (status) {  

            //GPS狀態為可見時  

            case LocationProvider.AVAILABLE:  

                Log.i(TAG, "當前GPS狀態為可見狀態");  

                break;  

            //GPS狀態為服務區外時  

            case LocationProvider.OUT_OF_SERVICE:  

                Log.i(TAG, "當前GPS狀態為服務區外狀態");  

                break;  

            //GPS狀態為暫停服務時  

            case LocationProvider.TEMPORARILY_UNAVAILABLE:  

                Log.i(TAG, "當前GPS狀態為暫停服務狀態");  

                break;  

            }  

        }  

      

        /** 

         * GPS開啟時觸發 

         */  

        public void onProviderEnabled(String provider) {  

            Location location=lm.getLastKnownLocation(provider);  

            updateView(location);  

        }  

      

        /** 

         * GPS禁用時觸發 

         */  

        public void onProviderDisabled(String provider) {  

            updateView(null);  

        }  

    };  

 

 

三、Location

 

Location,位置信息,通過Location可以獲取時間、經緯度、海拔等位置信息。上面采用locationListener裡面的onLocationChanged()來獲取location,下面講述如何主動獲取location。

 

[java]  

Location location=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);   system.out.println("時間:"+location.getTime());   system.out.println("經度:"+location.getLongitude());    

註意:Location location=new Location(LocationManager.GPS_PROVIDER)方式獲取的location的各個參數值都是為0。

 

 

 

四、GpsStatus.Listener

 

GpsStatus.Listener ,GPS狀態監聽,包括GPS啟動、停止、第一次定位、衛星變化等事件。

 

[java]  

//狀態監聽  

    GpsStatus.Listener listener = new GpsStatus.Listener() {  

        public void onGpsStatusChanged(int event) {  

            switch (event) {  

            //第一次定位  

            case GpsStatus.GPS_EVENT_FIRST_FIX:  

                Log.i(TAG, "第一次定位");  

                break;  

            //衛星狀態改變  

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:  

                Log.i(TAG, "衛星狀態改變");  

                //獲取當前狀態  

                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+"顆衛星");  

                break;  

            //定位啟動  

            case GpsStatus.GPS_EVENT_STARTED:  

                Log.i(TAG, "定位啟動");  

                break;  

            //定位結束  

            case GpsStatus.GPS_EVENT_STOPPED:  

                Log.i(TAG, "定位結束");  

                break;  

            }  

        };  

    };  

//綁定監聽狀態  

lm.addGpsStatusListener(listener);  

 

 

 

五、GpsStatus

 

GpsStatus,GPS狀態信息,上面在衛星狀態變化時,我們就用到瞭GpsStatus。

 

[java]  

//實例化      

GpsStatus gpsStatus = locationManager.getGpsStatus(null); // 獲取當前狀態      

//獲取默認最大衛星數      

int maxSatellites = gpsStatus.getMaxSatellites();       

//獲取第一次定位時間(啟動到第一次定位)      

int costTime=gpsStatus.getTimeToFirstFix();     

//獲取衛星      

Iterable<GpsSatellite> iterable=gpsStatus.getSatellites();     

//一般再次轉換成Iterator      

Iterator<GpsSatellite> itrator=iterable.iterator();  

 

六、GpsSatellite

GpsSatellite,定位衛星,包含衛星的方位、高度、偽隨機噪聲碼、信噪比等信息。

[java]  

//獲取衛星      

Iterable<GpsSatellite> iterable=gpsStatus.getSatellites();     

//再次轉換成Iterator      

Iterator<GpsSatellite> itrator=iterable.iterator();     

//通過遍歷重新整理為ArrayList      

ArrayList<GpsSatellite> satelliteList=new ArrayList<GpsSatellite>();      

int count=0;     

int maxSatellites=gpsStatus.getMaxSatellites();     

while (itrator.hasNext() && count <= maxSatellites) {       

    GpsSatellite satellite = itrator.next();       

    satelliteList.add(satellite);       

    count++;     

}      

System.out.println("總共搜索到"+count+"顆衛星");     

//輸出衛星信息      

for(int i=0;i<satelliteList.size();i++){     

    //衛星的方位角,浮點型數據      

    System.out.println(satelliteList.get(i).getAzimuth());     

    //衛星的高度,浮點型數據      

    System.out.println(satelliteList.get(i).getElevation());     

    //衛星的偽隨機噪聲碼,整形數據      

    System.out.println(satelliteList.get(i).getPrn());     

    //衛星的信噪比,浮點型數據      

    System.out.println(satelliteList.get(i).getSnr());     

    //衛星是否有年歷表,佈爾型數據      

    System.out.println(satelliteList.get(i).hasAlmanac());     

    //衛星是否有星歷表,佈爾型數據      

    System.out.println(satelliteList.get(i).hasEphemeris());     

    //衛星是否被用於近期的GPS修正計算      

    System.out.println(satelliteList.get(i).hasAlmanac());     

}  

 

 

 

為瞭便於理解,接下來模擬一個案例,如何在程序代碼中使用GPS獲取位置信息。

 

第一步:新建一個Android工程項目,命名為mygps,目錄結構如下

 

 

 

 

 

第二步:修改main.xml佈局文件,修改內容如下:

 

[html] view plaincopyprint?

<?xml version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

    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"/>  

</LinearLayout>  

 

 

 

第三步:實用Adnroid平臺的GPS設備,需要添加上權限

 

[html] 

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>     

 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  

 

 

 

第四步:修改核心組件activity,修改內容如下

 

[java] view plaincopyprint?

package jason.gprs;  

  

import java.util.Iterator;  

  

import android.app.Activity;  

import android.content.Context;  

import android.content.Intent;  

import android.location.Criteria;  

import android.location.GpsSatellite;  

import android.location.GpsStatus;  

import android.location.Location;  

import android.location.LocationListener;  

import android.location.LocationManager;  

import android.location.LocationProvider;  

import android.os.Bundle;  

import android.provider.Settings;  

import android.util.Log;  

import android.widget.EditText;  

import android.widget.Toast;  

  

public class MainActivity extends Activity {  

    private EditText editText;  

    private LocationManager lm;  

    private static final String TAG = "GpsActivity";  

  

    @Override  

    protected void onDestroy() {  

        // TODO Auto-generated method stub  

        super.onDestroy();  

        lm.removeUpdates(locationListener);  

    }  

  

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.activity_main);  

  

        editText = (EditText) findViewById(R.id.editText);  

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);  

  

        // 判斷GPS是否正常啟動  

        if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {  

            Toast.makeText(this, "請開啟GPS導航…", Toast.LENGTH_SHORT).show();  

            // 返回開啟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());  

        }  

  

        /** 

         * GPS狀態變化時觸發 

         */  

        public void onStatusChanged(String provider, int status, Bundle extras) {  

            switch (status) {  

            // GPS狀態為可見時  

            case LocationProvider.AVAILABLE:  

                Log.i(TAG, "當前GPS狀態為可見狀態");  

                break;  

            // GPS狀態為服務區外時  

            case LocationProvider.OUT_OF_SERVICE:  

                Log.i(TAG, "當前GPS狀態為服務區外狀態");  

                break;  

            // GPS狀態為暫停服務時  

            case LocationProvider.TEMPORARILY_UNAVAILABLE:  

                Log.i(TAG, "當前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, "第一次定位");  

                break;  

            // 衛星狀態改變  

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:  

                Log.i(TAG, "衛星狀態改變");  

                // 獲取當前狀態  

                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 + "顆衛星");  

                break;  

            // 定位啟動  

            case GpsStatus.GPS_EVENT_STARTED:  

                Log.i(TAG, "定位啟動");  

                break;  

            // 定位結束  

            case GpsStatus.GPS_EVENT_STOPPED:  

                Log.i(TAG, "定位結束");  

                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;  

    }  

}  

 

第五步:運行效果如下,嘿嘿,用的小米3的工程機做的測試,米3 發佈會吹噓的搜星速度確實很快:

發佈留言