在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便。
首先介绍一下地图包中的主要类:
MapController : 主要控制地图移动,伸缩,以某个GPS坐标为中心,控制MapView中的view组件,管理Overlay,提供View的基本功能。使用多种地图模式(地图模式(某些城市可实时对交通状况进行更新),卫星模式,街景模式)来查看Google Map。常用方法:animateTo(GeoPoint point) setCenter(GeoPoint point) setZoom(int zoomLevel) 等。
Mapview : 是用来显示地图的view, 它派生自android.view.ViewGroup。当MapView获得焦点,可以控制地图的移动和缩放。地图可以以不同的形式来显示出来,如街景模式,卫星模式等,通过setSatellite(boolean) setTraffic(boolean), setStreetView(boolean) 方法。
Overlay : 是覆盖到MapView的最上层,可以扩展其ondraw接口,自定义在MapView中显示一些自己的东西。MapView通过MapView.getOverlays()对Overlay进行管理。
Projection :MapView中GPS坐标与设备坐标的转换(GeoPoint和Point)。
定位系统包中的主要类:
LocationManager:本类提供访问定位服务的功能,也提供获取最佳定位提供者的功能。另外,临近警报功能也可以借助该类来实现。
LocationProvider:该类是定位提供者的抽象类。定位提供者具备周期性报告设备地理位置的功能。
LocationListener:提供定位信息发生改变时的回调功能。必须事先在定位管理器中注册监听器对象。
Criteria:该类使得应用能够通过在LocationProvider中设置的属性来选择合适的定位提供者。
Geocoder:用于处理地理编码和反向地理编码的类。地理编码是指将地址或其他描述转变为经度和纬度,反向地理编码则是将经度和纬度转变为地址或描述语言,其中包含了两个构造函数,需要传入经度和纬度的坐标。getFromLocation方法可以得到一组关于地址的数组。
下面开始地图定位实例的开发,在开发地图前需要 获取Android地图 API密钥 网上有很多资料,这里就不再复述。
首先要在manifest.xml中设置全相应的权限和maps库:
02 | android:icon = "@drawable/ic_launcher" |
03 | android:label = "@string/app_name" > |
05 | android:label = "@string/app_name" |
06 | android:name = ".MyMapActivity" > |
08 | < action android:name = "android.intent.action.MAIN" /> |
10 | < category android:name = "android.intent.category.LAUNCHER" /> |
13 | < span style = "color:#FF6666;" > |
14 | < uses-library android:name = "com.google.android.maps" /></ span > |
17 | < span style = "color:#FF6666;" > < uses-permission android:name = "android.permission.INTERNET" /> |
18 | < uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" /> |
19 | < uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" /></ span > |
在上面我标红的千万不要忘记。
layout下的main.xml:
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
02 | < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" |
03 | android:layout_width = "fill_parent" |
04 | android:layout_height = "fill_parent" |
05 | android:orientation = "vertical" > |
07 | < com.google.android.maps.MapView |
08 | android:id = "@+id/mapview" |
09 | android:layout_width = "fill_parent" |
10 | android:layout_height = "fill_parent" |
11 | android:apiKey = "008uu0x2a7GWlK2LzCW872afBAPLhJ-U2R26Wgw" |
下面是核心代码,重要的地方我做了注释:
001 | public class MyMapActivity extends MapActivity { |
002 | /** Called when the activity is first created. */ |
003 | private MapController mapController; |
004 | private MapView mapView; |
005 | private MyOverLay myOverLay; |
008 | public void onCreate(Bundle savedInstanceState) { |
009 | super .onCreate(savedInstanceState); |
010 | setContentView(R.layout.main); |
012 | LocationManager locationManager=(LocationManager) getSystemService(Context.LOCATION_SERVICE); |
013 | mapView=(MapView) this .findViewById(R.id.mapview); |
015 | mapView.setTraffic( true ); |
017 | mapView.setSatellite( false ); |
019 | mapView.setStreetView( false ); |
021 | mapView.setBuiltInZoomControls( true ); |
022 | mapView.setClickable( true ); |
023 | mapView.setEnabled( true ); |
025 | mapController=mapView.getController(); |
026 | mapController.setZoom( 15 ); |
028 | myOverLay= new MyOverLay(); |
029 | List<Overlay> overLays=mapView.getOverlays(); |
030 | overLays.add(myOverLay); |
032 | Criteria criteria= new Criteria(); |
033 | criteria.setAccuracy(Criteria.ACCURACY_FINE); |
034 | criteria.setAltitudeRequired( false ); |
035 | criteria.setBearingRequired( false ); |
036 | criteria.setCostAllowed( false ); |
037 | criteria.setPowerRequirement(Criteria.POWER_LOW); |
039 | String provider=locationManager.getBestProvider(criteria, true ); |
041 | Location location=locationManager.getLastKnownLocation(provider); |
042 | updateWithLocation(location); |
044 | locationManager.requestLocationUpdates(provider, 3000 , 0 , locationListener); |
048 | public boolean onCreateOptionsMenu(Menu menu) { |
050 | menu.add( 0 , 1 , 1 , "交通模式" ); |
051 | menu.add( 0 , 2 , 2 , "卫星模式" ); |
052 | menu.add( 0 , 3 , 3 , "街景模式" ); |
054 | return super .onCreateOptionsMenu(menu); |
057 | public boolean onOptionsItemSelected(MenuItem item) { |
059 | super .onOptionsItemSelected(item); |
060 | switch (item.getItemId()) { |
062 | mapView.setTraffic( true ); |
063 | mapView.setSatellite( false ); |
064 | mapView.setStreetView( false ); |
067 | mapView.setSatellite( true ); |
068 | mapView.setStreetView( false ); |
069 | mapView.setTraffic( false ); |
072 | mapView.setStreetView( true ); |
073 | mapView.setTraffic( false ); |
074 | mapView.setSatellite( false ); |
077 | mapView.setTraffic( true ); |
078 | mapView.setSatellite( false ); |
079 | mapView.setStreetView( false ); |
084 | private void updateWithLocation(Location location){ |
087 | myOverLay.setLocation(location); |
088 | GeoPoint geoPoint= new GeoPoint(( int )(location.getLatitude()*1E6), ( int )(location.getLongitude()*1E6)); |
090 | mapController.animateTo(geoPoint); |
091 | mapController.setZoom( 15 ); |
094 | private final LocationListener locationListener= new LocationListener() { |
097 | public void onStatusChanged(String provider, int status, Bundle extras) { |
103 | public void onProviderEnabled(String provider) { |
109 | public void onProviderDisabled(String provider) { |
115 | public void onLocationChanged(Location location) { |
117 | updateWithLocation(location); |
120 | class MyOverLay extends Overlay{ |
122 | private Location location; |
123 | public void setLocation(Location location){ |
124 | this .location=location; |
128 | public boolean draw(Canvas canvas, MapView mapView, boolean shadow, |
131 | super .draw(canvas, mapView, shadow); |
132 | Paint paint= new Paint(); |
133 | Point myScreen= new Point(); |
135 | GeoPoint geoPoint= new GeoPoint(( int )(location.getLatitude()*1E6), ( int )(location.getLongitude()*1E6)); |
136 | mapView.getProjection().toPixels(geoPoint, myScreen); |
137 | paint.setStrokeWidth( 1 ); |
138 | paint.setARGB( 255 , 255 , 0 , 0 ); |
139 | paint.setStyle(Paint.Style.STROKE); |
140 | Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.mypicture); |
142 | canvas.drawBitmap(bmp, myScreen.x, myScreen.y,paint); |
143 | canvas.drawText( "天堂没有路" , myScreen.x, myScreen.y, paint); |
149 | protected boolean isRouteDisplayed() { |
154 | public boolean onKeyDown( int keyCode, KeyEvent event) { |
157 | if (keyCode == KeyEvent.KEYCODE_BACK) { |
158 | AlertDialog.Builder builder = new AlertDialog.Builder( this ); |
159 | builder.setMessage( "你确定退出吗?" ) |
160 | .setCancelable( false ) |
161 | .setPositiveButton( "确定" , |
162 | new DialogInterface.OnClickListener() { |
163 | public void onClick(DialogInterface dialog, |
165 | MyMapActivity. this .finish(); |
167 | .killProcess(android.os.Process |
169 | android.os.Process.killProcess(android.os.Process.myTid()); |
170 | android.os.Process.killProcess(android.os.Process.myUid()); |
173 | .setNegativeButton( "返回" , |
174 | new DialogInterface.OnClickListener() { |
175 | public void onClick(DialogInterface dialog, |
180 | AlertDialog alert = builder.create(); |
185 | return super .onKeyDown(keyCode, event); |
接下来看一下运行后效果:
可以放大缩小:
可是使用menu键,切换不同的模式:
上面是切换到了卫星模式。由于地图需要耗费大量的网络资源,如果网络比较慢的话会等待很长时间。