首先介绍一下地图包中的主要类:
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库:
01 |
< application |
02 |
android:icon = "@drawable/ic_launcher" |
03 |
android:label = "@string/app_name" > |
04 |
< activity |
05 |
android:label = "@string/app_name" |
06 |
android:name = ".MyMapActivity" > |
07 |
< intent-filter > |
08 |
< action android:name = "android.intent.action.MAIN" /> |
09 |
|
10 |
< category android:name = "android.intent.category.LAUNCHER" /> |
11 |
</ intent-filter > |
12 |
</ activity > |
13 |
< span style = "color:#FF6666;" > |
14 |
< uses-library android:name = "com.google.android.maps" /></ span > |
15 |
</ application > |
16 |
|
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" > |
06 |
|
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" |
12 |
/> |
13 |
|
14 |
</ LinearLayout > |
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; |
006 |
|
007 |
@Override |
008 |
public void onCreate(Bundle savedInstanceState) { |
009 |
super .onCreate(savedInstanceState); |
010 |
setContentView(R.layout.main); |
011 |
|
012 |
LocationManager locationManager=(LocationManager) getSystemService(Context.LOCATION_SERVICE); |
013 |
mapView=(MapView) this .findViewById(R.id.mapview); |
014 |
//设置交通模式 |
015 |
mapView.setTraffic( true ); |
016 |
//设置卫星模式 |
017 |
mapView.setSatellite( false ); |
018 |
//设置街景模式 |
019 |
mapView.setStreetView( false ); |
020 |
//设置缩放控制 |
021 |
mapView.setBuiltInZoomControls( true ); |
022 |
mapView.setClickable( true ); |
023 |
mapView.setEnabled( true ); |
024 |
//得到MapController实例 |
025 |
mapController=mapView.getController(); |
026 |
mapController.setZoom( 15 ); |
027 |
|
028 |
myOverLay= new MyOverLay(); |
029 |
List<Overlay> overLays=mapView.getOverlays(); |
030 |
overLays.add(myOverLay); |
031 |
|
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); |
038 |
//取得效果最好的Criteria |
039 |
String provider=locationManager.getBestProvider(criteria, true ); |
040 |
//得到Location |
041 |
Location location=locationManager.getLastKnownLocation(provider); |
042 |
updateWithLocation(location); |
043 |
//注册一个周期性的更新,3秒一次 |
044 |
locationManager.requestLocationUpdates(provider, 3000 , 0 , locationListener); |
045 |
|
046 |
} |
047 |
@Override |
048 |
public boolean onCreateOptionsMenu(Menu menu) { |
049 |
// TODO Auto-generated method stub |
050 |
menu.add( 0 , 1 , 1 , "交通模式" ); |
051 |
menu.add( 0 , 2 , 2 , "卫星模式" ); |
052 |
menu.add( 0 , 3 , 3 , "街景模式" ); |
053 |
|
054 |
return super .onCreateOptionsMenu(menu); |
055 |
} |
056 |
@Override |
057 |
public boolean onOptionsItemSelected(MenuItem item) { |
058 |
// TODO Auto-generated method stub |
059 |
super .onOptionsItemSelected(item); |
060 |
switch (item.getItemId()) { |
061 |
case 1 : //交通模式 |
062 |
mapView.setTraffic( true ); |
063 |
mapView.setSatellite( false ); |
064 |
mapView.setStreetView( false ); |
065 |
break ; |
066 |
case 2 : //卫星模式 |
067 |
mapView.setSatellite( true ); |
068 |
mapView.setStreetView( false ); |
069 |
mapView.setTraffic( false ); |
070 |
break ; |
071 |
case 3 : //街景模式 |
072 |
mapView.setStreetView( true ); |
073 |
mapView.setTraffic( false ); |
074 |
mapView.setSatellite( false ); |
075 |
break ; |
076 |
default : |
077 |
mapView.setTraffic( true ); |
078 |
mapView.setSatellite( false ); |
079 |
mapView.setStreetView( false ); |
080 |
break ; |
081 |
} |
082 |
return true ; |
083 |
} |
084 |
private void updateWithLocation(Location location){ |
085 |
if (location!= null ){ |
086 |
//为绘制类设置坐标 |
087 |
myOverLay.setLocation(location); |
088 |
GeoPoint geoPoint= new GeoPoint(( int )(location.getLatitude()*1E6), ( int )(location.getLongitude()*1E6)); |
089 |
//定位到指定的坐标 |
090 |
mapController.animateTo(geoPoint); |
091 |
mapController.setZoom( 15 ); |
092 |
} |
093 |
} |
094 |
private final LocationListener locationListener= new LocationListener() { |
095 |
|
096 |
@Override |
097 |
public void onStatusChanged(String provider, int status, Bundle extras) { |
098 |
// TODO Auto-generated method stub |
099 |
|
100 |
} |
101 |
|
102 |
@Override |
103 |
public void onProviderEnabled(String provider) { |
104 |
// TODO Auto-generated method stub |
105 |
|
106 |
} |
107 |
|
108 |
@Override |
109 |
public void onProviderDisabled(String provider) { |
110 |
// TODO Auto-generated method stub |
111 |
|
112 |
} |
113 |
//当坐标改变时出发此函数 |
114 |
@Override |
115 |
public void onLocationChanged(Location location) { |
116 |
// TODO Auto-generated method stub |
117 |
updateWithLocation(location); |
118 |
} |
119 |
}; |
120 |
class MyOverLay extends Overlay{ |
121 |
|
122 |
private Location location; |
123 |
public void setLocation(Location location){ |
124 |
this .location=location; |
125 |
} |
126 |
|
127 |
@Override |
128 |
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, |
129 |
long when) { |
130 |
// TODO Auto-generated method stub |
131 |
super .draw(canvas, mapView, shadow); |
132 |
Paint paint= new Paint(); |
133 |
Point myScreen= new Point(); |
134 |
//将经纬度换成实际屏幕的坐标。 |
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); |
141 |
//把这张图片画到相应的位置。 |
142 |
canvas.drawBitmap(bmp, myScreen.x, myScreen.y,paint); |
143 |
canvas.drawText( "天堂没有路" , myScreen.x, myScreen.y, paint); |
144 |
return true ; |
145 |
|
146 |
} |
147 |
} |
148 |
@Override |
149 |
protected boolean isRouteDisplayed() { |
150 |
// TODO Auto-generated method stub |
151 |
return false ; |
152 |
} |
153 |
@Override |
154 |
public boolean onKeyDown( int keyCode, KeyEvent event) { |
155 |
// TODO Auto-generated method stub |
156 |
|
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, |
164 |
int id) { |
165 |
MyMapActivity. this .finish(); |
166 |
android.os.Process |
167 |
.killProcess(android.os.Process |
168 |
.myPid()); |
169 |
android.os.Process.killProcess(android.os.Process.myTid()); |
170 |
android.os.Process.killProcess(android.os.Process.myUid()); |
171 |
} |
172 |
}) |
173 |
.setNegativeButton( "返回" , |
174 |
new DialogInterface.OnClickListener() { |
175 |
public void onClick(DialogInterface dialog, |
176 |
int id) { |
177 |
dialog.cancel(); |
178 |
} |
179 |
}); |
180 |
AlertDialog alert = builder.create(); |
181 |
alert.show(); |
182 |
return true ; |
183 |
} |
184 |
|
185 |
return super .onKeyDown(keyCode, event); |
186 |
} |
187 |
} |
可以放大缩小:
可是使用menu键,切换不同的模式:
上面是切换到了卫星模式。由于地图需要耗费大量的网络资源,如果网络比较慢的话会等待很长时间。