Android GPS應用開發


轉載請注明出處: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

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

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);
    }
}
復制代碼
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);
    }
}
復制代碼

三、獲取定位信息

示例:通過手機實時獲取定位信息,包括用戶所在的經度、緯度、高度、方向、移動速度等

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("");
        }
    }
}
復制代碼
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)用於添加一個臨近警告。當用戶手機不斷臨近指定固定點時,當與該固定點的距離小於指定范圍時,系統可以觸發相應的處理。

示例:

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();
            }
        }
    }
}
復制代碼
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();
            }
        }
    }
復制代碼
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM