Android GPS应用程序设计

jopen 10年前

GPS简介

GPS是英文Global Positioning System(全球定位系统)的简称。GPS是20世纪70年代由美国陆海空三军联合研制的

新一代空间卫星导航定位系统 。其主要目的是为陆、海、空三大领域提供实时、 全天候和全球性的导航服务,并用于

情报收集、核爆监测和应急通讯等一些军事目的,经过20余年的研究实验,耗资300亿美元,到1994年3月,全球覆盖

率高达98%的24颗GPS卫星星座己布设完成。 


GPS定位原理 

GPS定位的基本原理是根据高速运动的卫星瞬间位置作为已知的起算数据,采用空间距离后方交会的方法,确定待测

点的位置。如图所示,假设t时刻在地面待测点上安置GPS接收机,可以测定GPS信号到达接收机的时间△t,再加上接

收机所接收到的卫星星历等其它数据可以确定以下四个方程式) 

20140424152355140.png


GPS的基本类

Android平台提供了一个android.location的包,有8个类。核心的3个类:

LocationManager类:作用与WifiManager、TelephonyManager等服务类的作用相似,所有与GPS定位相关的服务、

对象都由该对象产生。

LocationProvider类:定位提供者,GPS定位组件的抽象表示,通过该对象可以获取该定位组件的相关信息。

Location类:一个代表位置信息的抽象类。


使用它们来获取GPS定位信息的通用步骤为:

获取系统LocationManager对象

使用LocationManager,通过指定的定位设备LocationProvider来获取定位信息Location。

从Location对象中获取定位信息


LocationManager

LocationManager对象的获取:

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

常用方法

List<String> getAllProviders() 获得所有的LocationProvider列表

LocationProvider getProvider(String name) 根据名称来获取LocationProvider

List<String> getProviders(boolean enabledOnly) 获取所有可用的LocationProvider

List<String> getProviders(Criteria criteria, boolean enabledOnly) 根据指定条件获取满足该条件的全部LocationProvider的名称

String getBestProvider(Criteria criteria, boolean enabledOnly) 根据指定条件返回最优的LocationProvider对象

boolean isProviderEnabled(String provider) 判断指定名称的LocationProvider是否可用

Location getLastKnownLocation(String provider) 获取最近一次已知的Location

addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent) :添加一个趋近

警告

void removeProximityAlert(PendingIntent intent) 删除一个临近警告

void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) 

void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) 通过指定的

LocationProvider周期性地获取定位信息,并通过intent启动相应的组件

void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent)  通过指定的

LoctionProvider周期性地获取定位信息,并通过intent启动相应的组件



LocationProvider (定位提供者)

abstract int getAccuracy() 返回该LocationProvider的精度

String getName() 返回该LocationProvider的名称

int getPowerRequirement() 获取该LoctionProvider的电源需求

boolean hasMonetaryCost() 获取该LocationProvider是收费的还是免费的

boolean meetsCriteria(Criteria criteria) 判断该LocationProvider是否满足Criteria条件

boolean requiresCell() 判断该LocationProvider是否需要访问网络基站

boolean requiresNetwork() 判断该LocationProvider是否需要访问网络数据

boolean requiresSatellite() 判断该LoctionProvider是否需要访问基于卫星的定位系统

boolean supportsAltitude() 判断该LoctionProvider是否支持高度信息

boolean supportsBearing() 判断该LocationProvider是否支持方向信息

boolean supportsSpeed() 判断该LoctionProvider是否支持速度信息


Location(位置信息)

float getAccuracy() 获取定位信息的精度

double getAltitude() 获取定位信息的高度

float getBearing() 获取定位信息的方向

double getLatitude() 获取定位信息的纬度

double getLongitude() 获取定位信息的经度

String getProvider() 获取提供该定位信息的LocationProvider

float getSpeed() 获取定位信息的速度

long getTime() 

boolean hasAccuracy() 判断该定位信息是否有精度信息

boolean hasAltitude() 判断该定位信息是否有高度信息

boolean hasBearing() 判断该定位信息是否有方向信息

boolean hasSpeed() 判断该定位信息是否有速度信息


获取定位信息

1 获取所有可用的LocationProvider

LocationManager提供了一个getAllProvider()方法来获取系统所有可用的LocationProvider

系统共有三种类型的LocationProvider

network : 由LocationManager.NETWORK_PROVIDER常量表示

gps : 由LocationManager.GPS_PROVIDER常量表示

passive : 由LoctionManager.PASSIVE_PROVIDER常量表示

2 通过名称获得指定getProvider(String name)

3 根据Criteria获得getProviders(Criteria criteria, boolean enabledOnly) 

Criteria:代表了一个“过滤”条件,它提供了一些方法来设置条件

void setAccuracy(int accuracy) 

void setAltitudeRequired(boolean altitudeRequired) 

void setBearingAccuracy(int accuracy) 

void setBearingRequired(boolean bearingRequired) 

获取LocationManager对象后,可通过指定的LocationProvider获取定位信息,如:经度、维度、高度、移动速度等。

GPS访问权限

 <uses-permission android:name=“android.permission.ACCESS_FINE_LOCATION”>


趋近警告

趋近警告就是当用户手机临近指定点时,当与该点的距离小于指定范围时,系统可触发相应的处理,该功能能够对我们

进入或退出某个设定的区域进行提示。

LocationManager提供方法:addProximityAlert(double latitude, double longitude, float radius, long expiration, 

PendingIntent intent),

latitude经度、longitude纬度, radius区域半径, expiration指定经过多少毫秒过期,-1为永不过期,PendingIntent指

定触发的Intent组件。

要实现此功能需要两个步骤:

一是获得LocationManager实例,调用其方法addProximityalert并添加趋近提示;

二是定义一个广播接收器,当设备进入设定区域时提醒用户。


例子代码:

获取LocationProvider:

获取所有的LocationProvider的名称

    // 获取LocationManager对象        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);                // 获取所有的LocationProvider的名称        List<String> providerNames = mLocationManager.getAllProviders();  
</div> </div> 通过名称获取指定LocationProvider

    //获取基于GPS的LocationProvider        LocationProvider locProvider = lm.getProvider(LocatinManager.GPS_PROVIDER)  
</div> </div> 根据Criteria获得LocationProvider
                  mProviders = (ListView) findViewById(R.id.providers);        // 获取系统的LocationManager对象        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);        // 创建一个LocationProvider的过滤条件        Criteria cri = new Criteria();        // 设置要求LocationProvider必须是免费的。        cri.setCostAllowed(false);                // 设置要求LocationProvider能提供高度信息        cri.setAltitudeRequired(true);          // 设置要求LocationProvider能提供方向信息        cri.setBearingRequired(true);        // 获取系统所有符合条件的LocationProvider的名称        List<String> providerNames = mLocationManager.getProviders(cri, true);  
</div> </div>


获取定位数据:

    // 创建LocationManager对象                mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);                // 从GPS获取最近的定位信息                Location location = mLocationManager                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);                // 使用location根据EditText的显示                updateView(location);                // 设置每2秒获取一次GPS的定位信息                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,                        2000, 8, new LocationListener() {                            @Override                            public void onLocationChanged(Location location) {                                // 当GPS定位信息发生改变时,更新位置                                updateView(location);                            }                                    @Override                            public void onProviderDisabled(String provider) {                                updateView(null);                            }                                    @Override                            public void onProviderEnabled(String provider) {                                // 当GPS LocationProvider可用时,更新位置                                updateView(mLocationManager                                        .getLastKnownLocation(provider));                            }                                    @Override                            public void onStatusChanged(String provider, int status,                                    Bundle extras) {                            }                        });                    }                    // 更新EditText中显示的内容            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());                    mEditText.setText(sb.toString());                } else {                    // 如果传入的Location对象为空则清空EditText                    mEditText.setText("");                }  
</div> </div>

    <!-- 授权获取定位信息 -->            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
</div> </div> 该程序需要有访问GPS信号的权限,因此需要在AndroidManifest.xml文件中增加授权信息. 用于从Location中获取定位信息,包括用户的经度,纬度,高度,方向,和移动速度等信息,并通过LocationManager设置了

个监听器,该监听器负责每隔3秒向LocationProvider请求一次定位信息,当LocationProvider可用时,不可用时或提供的定

位信息发生改变时,系统会回调对应的方法更新界面.

如果该程序与Google Map结合,让该程序根据GPS提供的信息实时地显示用户在地图上的位置,即可开发GPS导航系统


趋近警告:

    // 定位服务管理器对象                LocationManager locationManager;                // 通过getSystemService方法获得LocationManager对象                locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);                // 定义万里学院4号楼的大致经度、纬度                double longitude = 123.427109;                double latitude = 41.764998;                // 定义半径(2000米)                 float radius = 2000;                        // 定义Intent                Intent intent = new Intent(this, ProximityAlertReciever.class);                // 将Intent包装成PendingIntent                PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1,                        intent, 0);                        // 添加临近警告                locationManager.addProximityAlert(latitude, longitude, radius, -1,                        pendingIntent);  
</div> </div> 对应启动的BroadcastReceiver :
    public class ProximityAlertReciever extends BroadcastReceiver {            @Override            public void onReceive(Context context, Intent intent) {                        // 获取是否为进入指定区域                boolean isEnter = intent.getBooleanExtra(                        LocationManager.KEY_PROXIMITY_ENTERING, false);                if (isEnter) {                    // 显示提示信息                    Toast.makeText(context, "您已经接近万里学院4号楼", Toast.LENGTH_LONG).show();                } else {                    // 显示提示信息                    Toast.makeText(context, "您已经离开万里学院4号楼", Toast.LENGTH_LONG).show();                }            }        }  
</div> </div>
    <!-- 授权获取定位信息 -->            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>            <uses-permission android:name="android.permission.INTERNET"/>  
</div> </div>


计算两点距离:

final float[] results = new float[3];                Location.distanceBetween(20.123, 30.05644, 30.124, 40.543, results);            final float bearing = results[1];            mEditText.setText(String.valueOf(results[0]) + "米");  
</div> </div> 来自:http://blog.csdn.net/coslay/article/details/24416085