GPS 导航

时间:2023-02-15 01:07:18

简介

实际上Android应用可以通过GPS来获取定位信息。上一章中我们已经介绍了如何通过GPS来获取定位信息,因此如果把前面介绍的GPS定位与本章中Google Map结合起来,就可以非常方便地开发出GPS导航应用。 10.6.1 随着Location的变化,Google Map定位到不同的位置

示例:将Google Map和Location结合起来,实现的具体功能是:随着Location的变化,Google Map定位到不同的位置

第一步:修改主布局文件的代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <com.google.android.maps.MapView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/mapView"
        android:clickable="true"
        android:apiKey="0ZunUBGNC7PX6f_EXkmsJJA1436uoJ3dAsWhXuw" />
</LinearLayout>

第二步:修改MainActivity类代码如下所示:

public class MainActivity extends MapActivity {
	MapView mapView = null;
	MapController controller = null;
	GeoPoint point = null;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mapView = (MapView) findViewById(R.id.mapView);
		mapView.setClickable(true);
		mapView.setBuiltInZoomControls(true);
		int latitudeE6 = (int) 34.752014421190424 * 1000000;
		int longitudeE6 = (int) 113.66632941527462 * 1000000;
		point = new GeoPoint(latitudeE6, longitudeE6);
		controller = mapView.getController();
		controller.animateTo(point);
		controller.setZoom(mapView.getZoomLevel()-1);
		controller.setCenter(point);
		LocationManager manager = (LocationManager) 
getSystemService(Context.LOCATION_SERVICE);
		manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
 1200, 0, listener);
	}
	LocationListener listener = new LocationListener() {
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
		public void onProviderEnabled(String provider) {
		}
		public void onProviderDisabled(String provider) {
		}
		public void onLocationChanged(Location location) {	//修改定位点的坐标值
			int latitudeE6 = (int) location.getLatitude() * 1000000;
			int longitudeE6 = (int) location.getLongitude()* 1000000;
			point = new GeoPoint(latitudeE6, longitudeE6);
			controller.animateTo(point);
			controller.setZoom(mapView.getZoomLevel()+1);
		}
	};
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

刚启动时程序运行效果如下图所示: GPS 导航

在Emulator Controler中输入不同的经纬度,会定位到不同的位置: GPS 导航

输入不同经纬度后程序的运行效果所示: GPS 导航

示例:开发一个非常简单的GPS导航系统,要求该应用程序每隔30秒获取一次GPS定位数据,当程序得到 GPS定位信息之后,程序就把Google Map定位到该位置,这样就可以在地图上实时地跟踪设备的移动位置。

本程序的界面非常简单,只提供一个MapView来显示设备在地图上的位置,具体代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <com.google.android.maps.MapView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/mapView"
        android:clickable="true"
        android:apiKey="0ZunUBGNC7PX6f_EXkmsJJA1436uoJ3dAsWhXuw" />
</LinearLayout>

然后自定义图层类,最终代码如下所示:

class PosOverLay extends Overlay {
	Bitmap posBitmap; // 定义该PosOverLay所绘制的位图
	GeoPoint point; // 定义该PosOverLay绘制位图的位置
	public PosOverLay(GeoPoint point, Bitmap posBitmap) {
		this.point = point;
		this.posBitmap = posBitmap;
	}
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		if (!shadow) {
			Projection proj = mapView.getProjection();// 获取MapView的Projection对象
			Point p = new Point();
			proj.toPixels(point, p); // 将真实的地理坐标转化为屏幕上的坐标
			// 在指定位置绘制图片
			canvas.drawBitmap(posBitmap, p.x - posBitmap.getWidth() / 2, 
p.y - posBitmap.getHeight(), null);
		}
	}
}

最后修改MainActivity类的代码如下所示:

public class MainActivity extends MapActivity {
	MapView mapView;
	MapController controller;
	Bitmap posBitmap;
	LocationManager locManager;
	@Override
	protected void onCreate(Bundle status) {
		super.onCreate(status);
		setContentView(R.layout.gps);
		posBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tool);
		mapView = (MapView) findViewById(R.id.mapView); // 获得界面上MapView对象
		mapView.setBuiltInZoomControls(true); // 设置显示放大、缩小的按钮
		controller = mapView.getController();// 创建MapController对象
		// 获取LocationManager对象
		locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		// 设置每30秒获取一次GPS的定位信息
		locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 10,
 new LocationListener() {
			@Override// 当GPS定位信息发生改变时,更新位置
			public void onLocationChanged(Location location) {
				updateMapView(location);
			}
			@Override
			public void onProviderDisabled(String provider) {
			}
			@Override//  当GPS LocationProvider可用时,更新位置
			public void onProviderEnabled(String provider) {
				updateMapView(locManager.getLastKnownLocation(provider));
			}
			@Override
			public void onStatusChanged(String provider,int status,Bundle extras) {
			}
		});
	}
	@Override
	protected boolean isRouteDisplayed() {
		return true;
	}
	// 根据Location来更新MapView
	private void updateMapView(Location location) {
		// 将Location对象中的经、纬度信息包装成GeoPoint对象
		GeoPoint gp = new GeoPoint((int) (location.getLatitude() * 1E6), 
(int) (location.getLongitude() * 1E6));
		mapView.displayZoomControls(true); // 设置显示放大缩小按钮
		controller.animateTo(gp); // 将地图移动到指定的地理位置
		List<Overlay> ol = mapView.getOverlays();// 获得MapView上原有的Overlay对象
		ol.clear();// 清除原有的Overlay对象
		ol.add(new PosOverLay(gp, posBitmap)); // 添加一个新的OverLay对象
	}
}

因为本程序需要使用Google Map,因此需要在功能清单文件中添加如下权限:

<!-开启访问internet的权限 ->
<uses-permission android:name="android.permission.INTERNET" />	
<!-用于获取”精确的”位置数据,比如GPS数据->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

运行程序,打开Emulator Controller,更换不同的经纬度,发送数据,程序运行结果如下图所示: GPS 导航