在第一讲的例子中,我们已经看到如何使用com.google.android,maps.MapView组件来开发一个简单的google地图程序,这一讲我们将看到,如何使用android手机自带的GPS系统来定位自己的位置,并在地图层中对此进行标识。
GPS 是英文Global Positioning System(全球定位系统)的简称,而其中文简称为“球位系”。GPS是20世纪70年代由美国陆海空三军联合研制的新一代空间卫星导航定位系统 。其主要目的是为陆、海、空三大领域提供实时、 全天候和全球性的导航服务,并用于情报收集、核爆监测和应急通讯等一些军事目的经过20余年的研究实验,耗资300亿美元,到1994年3月,全球覆盖率高达98%的24颗GPS卫星星座己布设完成。
我们在前面那个程序的基础上进行进一步的开发。
要在android程序中使用GPS进行开发,首先,必须在Manifest.xml文件中声明使用权限,在
接着,在MapView组件前面声明一些标签组件用于显示当前的经纬度信息:
- android:layout_height="wrap_content" android:stretchColumns="1">
- android:layout_height="wrap_content" android:text="GPS位置:" />
- android:layout_height="wrap_content" android:text="经度:" />
- android:layout_width="fill_parent" android:layout_height="wrap_content" />
- android:layout_height="wrap_content" android:text="纬度:" />
- android:layout_width="fill_parent" android:layout_height="wrap_content" />
上面的TableLayout是用于布局的组件,以后如果写布局方面的教程,在跟大家详细讲解吧。
然后,在程序里面添加一些用于控制经纬度信息显示的TextView私有域:
- private TextView textLongitude;//精度显示
- private TextView textLatitude;//纬度显示
在onCreat方法中对他们进行初始化:
- //通过ID初始化组件
- textLongitude = (TextView)findViewById(R.id.main_longitude);
- textLatitude = (TextView)findViewById(R.id.main_latitude);
接着声明位置管理器,与位置信息监听器的组件:
- private LocationManager locationManager;//位置管理器
- private LocationListener locationListener;//位置监听器
并在onCreat方法中分别对它们进行初始化:
- //从系统服务中获得位置管理器
- locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
- //初始化位置监听器
- locationListener = new LocationListener() {
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- }
- @Override
- public void onProviderEnabled(String provider) {
- }
- @Override
- public void onProviderDisabled(String provider) {
- }
- @Override
- public void onLocationChanged(Location location) {
- //当位置信息更新时,更新其位置信息的界面显示
- updateLocation(location);
- }
- };
getSystemService方法时Activity的方法,用于或的系统的某些服务,这里我们获得的自然是GPS服务。实例域locationListener是一个位置信息监听器,它有四个方法,这里我们主要关心它的onLocationChanged方法,当位置信息发生变化时,该方法将被调用,这里,当位置信息发生变化时,我们自然是需要修改GPS坐标信息的,因此调用updateLocation方法,下面是它的定义:
- private void updateLocation(Location location) {
- if (location != null) {
- double longitude = location.getLongitude();// 经度
- double latitude = location.getLatitude();// 纬度
- //刷新经纬度信息显示
- textLongitude.setText(longitude + "");
- textLatitude.setText(latitude + "");
- } else{
- textLongitude.setText("没有位置信息");
- textLatitude.setText("没有位置信息");
- }
- }
再看下面一段定义在onCreat方法中的代码:
- //设置服务提供者,这里提供者设置为GPS卫星
- String provider = LocationManager.GPS_PROVIDER;
- Location location = locationManager.getLastKnownLocation(provider);//获得最新的位置
- updateLocation(location);//更新位置信息显示
- //设置监听器监听位置信息,最低的更新频率为3秒,位置跨度为10米
- locationManager.requestLocationUpdates(provider, 3000, 10, locationListener);
这段代码设定GPS位置信息的提供者为GPS卫星,并尽快显示上一次GPS服务所得到的位置信息,最后一段代码相当于是在注册监听器,设置其最低的更新频率为3秒,位置跨度为10米。
注意,因为本程序使用了GPS服务,所以在使用本程序之前得提前打开手机的GPS服务。一般是在:设置à位置,然后在使用GPS卫星项打钩。
现在关于GPS部分就差不多讲完了,但是程序目前还没有和Map组件关联起来,在之后我们将看到如何使用地图层类在地图中进行标识。
今天我们来看一下如何将得到的GPS位置用于google地图中进行定位,首先我们得了解什么事图层类(Overlay),该类是一个描述了将呈现在地图顶层的地图层的基类,如果我们要给地图新添加一个图层,首先得继承这个类,然后创建一个它的实例,将它添加到MapView.getOverlays()返回的Overlay线性表中去。
因此,本程序首先增加一个类MyLocationOverlay,该类继承了Overlay,定义一个该类的构造方法:
复制代码
- public MyLocationOverlay(Resources res){
- this.res = res;
- }
res是我们自己定义的一个Resources类型的实例域,用于获得将要显示的图片资源,接着再增加两个实例域:
复制代码
- private Double longitude;//经度
- private Double latitude;//纬度
用于存放经纬度位置信息,接着设置一个可以set他们的方法:
复制代码
- //在更新坐标时,设置该坐标,以便画图
- public void setLocation(double longitude, double latitude) {
- this.longitude = longitude;
- this.latitude = latitude;
- }
重写父类的draw方法,当更新地图时,它将被调用。
复制代码
- @Override
- public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
- super.draw(canvas, mapView, shadow);
- //GPS服务没有开通或不支持
- if(longitude == null || latitude == null)
- return false;
- // 将经纬度转换成实际地图坐标
- GeoPoint tmpGeoPoint = new GeoPoint((int)(latitude * 1E6), (int)(longitude * 1E6));
- //将地图坐标转换位屏幕位置
- Point myScreenCoords = new Point();
- mapView.getProjection().toPixels(tmpGeoPoint, myScreenCoords);
- //设置画笔格式
- Paint paint = new Paint();
- paint.setStrokeWidth(1);
- paint.setARGB(255, 255, 0, 0);
- paint.setStyle(Paint.Style.STROKE);
- //添加地图层
- Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.icon);
- canvas.drawBitmap(bmp, myScreenCoords.x, myScreenCoords.y, paint);
- canvas.drawText("Here am I", myScreenCoords.x, myScreenCoords.y, paint);
- return true;
- }
在添加地图层时或得的图片资源是用于标识你的位置所在,你可以自己找图片放进drawble文件中去,然后在这里解码它们,这里为了省麻烦就直接用系统的那个图片了。
接下来,在主类中我们再添加两个实例域:
复制代码
- private MapController mMapController;// 地图管理器
- private MyLocationOverlay myPosition;// 我的位置图层
在onCreat方法中我们首先要获得对地图组件的引用,然后分别对他们进行初始化:
复制代码
- MapView mMapView = (MapView) findViewById(R.id.main_MapView);
- mMapController = mMapView.getController();// 获得地图管理器
- mMapController.setZoom(17);// 设置缩放等级
- myPosition = new MyLocationOverlay(getResources());// 初始化我的位置图层
- List
list = mMapView.getOverlays();// 获得地图层集合
- list.add(myPosition);// 将我的位置图层加入该地图层集合
当地图更新时,list中的所有图层都会被调用draw方法,重新绘制图层。
注意,这段代码必须放在updateLocation(location);的前面,因为我们接下来将往其中添加更新地图层的代码,否则会抛出空指针异常。
在updateLocation中新增的代码:
复制代码
- // 更新地图显示
- myPosition.setLocation(longitude, latitude);// 设置我的位置
- GeoPoint point = new GeoPoint((int) (latitude * 1E6),
- (int) (longitude * 1E6));// 获得经纬度点
- mMapController.animateTo(point);// 地图指向新的坐标
没当GPS位置信息更新后,就会重新绘制地图层更新你的位置,下面是运行示例: