Android定位功能

来源:互联网 发布:ucosiii源码下载地址 编辑:程序博客网 时间:2024/06/05 00:56

废话不多说,直接开始说说与实现Android定位有关的API吧。

  这些API都在android.location包下,一共有三个接口和八个类。它们配合使用即可实现定位功能。

 

  三个接口:

  GpsStatus.Listener: 这是一个当GPS状态发生改变时,用来接收通知的接口。

  GpsStatus.NmeaListener: 这是一个用来从GPS里接收Nmea-0183(为海用电子设备制定的标准格式)信息的接口。

  LocationListener: 位置监听器,用于接收当位置信息发生改变时从LocationManager接收通知的接口。

 

  八个类:

  Address: 描述地址的类,比如:北京天安门

  Criteria: 用于描述Location Provider标准的类,标准包括位置精度水平,电量消耗水平,是否获取海拔、方位信息,是否允许接收付费服务。

  GeoCoder: 用于处理地理位置的编码。

  GpsSatellite: 和GpsStatus联合使用,用于描述当前GPS卫星的状态。

  GpsStatus: 和GpsStatus.Listener联合使用,用于描述当前GPS卫星的状态。

  Location: 用于描述位置信息。

  LocationManager: 通过此类获取和调用系统位置服务

  LocationProvider: 用于描述Location Provider的抽象超类,一个LocationProvider应该能够周期性的报告当前设备的位置信息。

 

  这里通过一个代码示例,演示一下如何实现定位。

  首先,在AndroidManifest.xml清单文件里需要加入ACCESS_FINE_LOCATION权限

1<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
其次,实现代码如下:
001package com.test;
002  
003 import java.io.IOException;
004 import java.util.List;
005  
006 import android.app.Activity;
007 import android.location.Address;
008 import android.location.Criteria;
009 import android.location.Geocoder;
010 import android.location.Location;
011 import android.location.LocationListener;
012 import android.location.LocationManager;
013 import android.os.Bundle;
014 import android.util.Log;
015 import android.widget.Toast;
016  
017 public class MainActivity extends Activity {
018     @Override
019     public void onCreate(Bundle savedInstanceState) {
020        super.onCreate(savedInstanceState);
021        setContentView(R.layout.main);
022         
023        //获取到LocationManager对象
024        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
025        //创建一个Criteria对象
026        Criteria criteria = new Criteria();
027        //设置粗略精确度
028        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
029        //设置是否需要返回海拔信息
030        criteria.setAltitudeRequired(false);
031        //设置是否需要返回方位信息
032        criteria.setBearingRequired(false);
033        //设置是否允许付费服务
034        criteria.setCostAllowed(true);
035        //设置电量消耗等级
036        criteria.setPowerRequirement(Criteria.POWER_HIGH);
037        //设置是否需要返回速度信息
038        criteria.setSpeedRequired(false);
039  
040        //根据设置的Criteria对象,获取最符合此标准的provider对象
041        String currentProvider = locationManager.getBestProvider(criteria, true);
042        Log.d("Location""currentProvider: " + currentProvider);
043        //根据当前provider对象获取最后一次位置信息
044        Location currentLocation = locationManager.getLastKnownLocation(currentProvider);
045        //如果位置信息为null,则请求更新位置信息
046        if(currentLocation == null){
047            locationManager.requestLocationUpdates(currentProvider, 00, locationListener);
048        }
049        //直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
050        //每隔10秒获取一次位置信息
051        while(true){
052            currentLocation = locationManager.getLastKnownLocation(currentProvider);
053            if(currentLocation != null){
054                Log.d("Location""Latitude: " + currentLocation.getLatitude());
055                Log.d("Location""location: " + currentLocation.getLongitude());
056                break;
057            }else{
058                Log.d("Location""Latitude: " 0);
059                Log.d("Location""location: " 0);
060            }
061            try {
062                Thread.sleep(10000);
063            catch (InterruptedException e) {
064                 Log.e("Location", e.getMessage());
065            }
066        }
067         
068        //解析地址并显示
069        Geocoder geoCoder = new Geocoder(this);
070        try {
071            int latitude = (int) currentLocation.getLatitude();
072            int longitude = (int) currentLocation.getLongitude();
073            List<Address> list = geoCoder.getFromLocation(latitude, longitude, 2);
074            for(int i=0; i<list.size(); i++){
075                Address address = list.get(i);
076                Toast.makeText(MainActivity.this, address.getCountryName() + address.getAdminArea() + address.getFeatureName(), Toast.LENGTH_LONG).show();
077            }
078        catch (IOException e) {
079            Toast.makeText(MainActivity.this,e.getMessage(), Toast.LENGTH_LONG).show();
080        }
081         
082     }
083      
084     //创建位置监听器
085     private LocationListener locationListener = new LocationListener(){
086         //位置发生改变时调用
087         @Override
088         public void onLocationChanged(Location location) {
089             Log.d("Location""onLocationChanged");
090             Log.d("Location""onLocationChanged Latitude" + location.getLatitude());
091                  Log.d("Location""onLocationChanged location" + location.getLongitude());
092         }
093  
094         //provider失效时调用
095         @Override
096         public void onProviderDisabled(String provider) {
097             Log.d("Location""onProviderDisabled");
098         }
099  
100         //provider启用时调用
101         @Override
102         public void onProviderEnabled(String provider) {
103             Log.d("Location""onProviderEnabled");
104         }
105  
106         //状态改变时调用
107         @Override
108         public void onStatusChanged(String provider, int status, Bundle extras) {
109             Log.d("Location""onStatusChanged");
110         }
111     };
112 }

由于代码里的Criteria对象对位置精度要求并不高,所以一般会返回“network”作为provider,而基于network的定位往往会存在一定的位置偏差,这对于需要精确定位的应用程序来说,显然不合要求。这时,需要则需要用到基于GPS的定位方法了

在实现GPS定位前,先了解一下GPS的部分特性:

  1. GPS定位需要依靠3颗或3颗以上的卫星。

  2. GPS定位受环境影响较大,在晴朗的空地上,较容易搜索到卫星,而在室内通常是无法搜索到卫星的。

  3. GPS定位需要使用GPS功能模块,而GPS功能模块的耗电量是巨大的。

  在Android系统中,实现GPS定位的思路应该是:

  1. 获取GPS的Location Provider。

  2. 讲此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。

  3. 创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)

001public class MainActivity extends Activity {
002     private LocationManager locationManager;
003     private GpsStatus gpsstatus;
004     @Override
005     public void onCreate(Bundle savedInstanceState) {
006        super.onCreate(savedInstanceState);
007        setContentView(R.layout.main);
008         
009        //获取到LocationManager对象
010        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
011         
012        //根据设置的Criteria对象,获取最符合此标准的provider对象
013        String currentProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER).getName();
014         
015        //根据当前provider对象获取最后一次位置信息
016        Location currentLocation = locationManager.getLastKnownLocation(currentProvider);
017        //如果位置信息为null,则请求更新位置信息
018        if(currentLocation == null){
019            locationManager.requestLocationUpdates(currentProvider, 00, locationListener);
020        }
021        //增加GPS状态监听器
022        locationManager.addGpsStatusListener(gpsListener);
023         
024        //直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
025        //每隔10秒获取一次位置信息
026        while(true){
027            currentLocation = locationManager.getLastKnownLocation(currentProvider);
028            if(currentLocation != null){
029                Log.d("Location""Latitude: " + currentLocation.getLatitude());
030                Log.d("Location""location: " + currentLocation.getLongitude());
031                break;
032            }else{
033                Log.d("Location""Latitude: " 0);
034                Log.d("Location""location: " 0);
035            }
036            try {
037                Thread.sleep(10000);
038            catch (InterruptedException e) {
039                 Log.e("Location", e.getMessage());
040            }
041        }
042     }
043      
044     private GpsStatus.Listener gpsListener = new GpsStatus.Listener(){
045         //GPS状态发生变化时触发
046         @Override
047         public void onGpsStatusChanged(int event) {
048             //获取当前状态
049             gpsstatus=locationManager.getGpsStatus(null);
050             switch(event){
051                 //第一次定位时的事件
052                 case GpsStatus.GPS_EVENT_FIRST_FIX:
053                     break;
054                 //开始定位的事件
055                 case GpsStatus.GPS_EVENT_STARTED:
056                     break;
057                 //发送GPS卫星状态事件
058                 case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
059                     Toast.makeText(MainActivity.this"GPS_EVENT_SATELLITE_STATUS", Toast.LENGTH_SHORT).show();
060                     Iterable<GpsSatellite> allSatellites = gpsstatus.getSatellites();  
061                     Iterator<GpsSatellite> it=allSatellites.iterator();
062                     int count = 0;
063                     while(it.hasNext())  
064                     {  
065                         count++;
066                     }
067                     Toast.makeText(MainActivity.this"Satellite Count:" + count, Toast.LENGTH_SHORT).show();
068                     break;
069                 //停止定位事件
070                 case GpsStatus.GPS_EVENT_STOPPED:
071                     Log.d("Location""GPS_EVENT_STOPPED");
072                     break;
073             }
074         }
075     };
076      
077      
078     //创建位置监听器
079     private LocationListener locationListener = new LocationListener(){
080         //位置发生改变时调用
081         @Override
082         public void onLocationChanged(Location location) {
083             Log.d("Location""onLocationChanged");
084         }
085  
086         //provider失效时调用
087         @Override
088         public void onProviderDisabled(String provider) {
089             Log.d("Location""onProviderDisabled");
090         }
091  
092         //provider启用时调用
093         @Override
094         public void onProviderEnabled(String provider) {
095             Log.d("Location""onProviderEnabled");
096         }
097  
098         //状态改变时调用
099         @Override
100         public void onStatusChanged(String provider, int status, Bundle extras) {
101             Log.d("Location""onStatusChanged");
102         }
103     };
104 }

通过以上代码中的注释部分,可以清晰的知道Android定位功能里相关方法的具体含义。希望对大家有用。

  另外,因为GPS的自身特性,此代码在室内几乎无法定位,所以建议再真正的实际项目里,至少使用network和GPS两种不同的Location Provider实现定位功能。


原创粉丝点击