在Android開發(fā)中地圖和定位是很多軟件不可或缺的內(nèi)容,這些特色功能也給人們帶來了很多方便。
首先介紹一下地圖包中的主要類:
MapController:? 主要控制地圖移動,伸縮,以某個(gè)GPS坐標(biāo)為中心,控制MapView中的view組件,管理Overlay,提供View的基本功能。使用多種地圖模式(地圖模式(某些城市可實(shí)時(shí)對交通狀況進(jìn)行更新),衛(wèi)星模式,街景模式)來查看Google Map。常用方法:animateTo(GeoPoint point)? setCenter(GeoPoint point)? setZoom(int zoomLevel) 等。
Mapview? : 是用來顯示地圖的view, 它派生自android.view.ViewGroup。當(dāng)MapView獲得焦點(diǎn),可以控制地圖的移動和縮放。地圖可以以不同的形式來顯示出來,如街景模式,衛(wèi)星模式等,通過setSatellite(boolean)? setTraffic(boolean), setStreetView(boolean) 方法。
Overlay:是覆蓋到MapView的最上層,可以擴(kuò)展其ondraw接口,自定義在MapView中顯示一些自己的東西。MapView通過MapView.getOverlays()對Overlay進(jìn)行管理。
Projection:MapView中GPS坐標(biāo)與設(shè)備坐標(biāo)的轉(zhuǎn)換(GeoPoint和Point)。
定位系統(tǒng)包中的主要類:
LocationManager:本類提供訪問定位服務(wù)的功能,也提供獲取最佳定位提供者的功能。另外,臨近警報(bào)功能也可以借助該類來實(shí)現(xiàn)。
LocationProvider:該類是定位提供者的抽象類。定位提供者具備周期性報(bào)告設(shè)備地理位置的功能。
LocationListener:提供定位信息發(fā)生改變時(shí)的回調(diào)功能。必須事先在定位管理器中注冊監(jiān)聽器對象。
Criteria:該類使得應(yīng)用能夠通過在LocationProvider中設(shè)置的屬性來選擇合適的定位提供者。
Geocoder:用于處理地理編碼和反向地理編碼的類。地理編碼是指將地址或其他描述轉(zhuǎn)變?yōu)榻?jīng)度和緯度,反向地理編碼則是將經(jīng)度和緯度轉(zhuǎn)變?yōu)榈刂坊蛎枋稣Z言,其中包含了兩個(gè)構(gòu)造函數(shù),需要傳入經(jīng)度和緯度的坐標(biāo)。getFromLocation方法可以得到一組關(guān)于地址的數(shù)組。
下面開始地圖定位實(shí)例的開發(fā),在開發(fā)地圖前需要獲取Android地圖API密鑰網(wǎng)上有很多資料,這里就不再復(fù)述。
首先要在manifest.xml中設(shè)置全相應(yīng)的權(quán)限和maps庫:
[html]view plaincopy
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
android:label="@string/app_name"
android:name=".MyMapActivity">
在上面我標(biāo)紅的千萬不要忘記。
layout下的main.xml:
[html]view plaincopy
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="008uu0x2a7GWlK2LzCW872afBAPLhJ-U2R26Wgw"
/>
下面是核心代碼,重要的地方我做了注釋:
[html]view plaincopy
public?class?MyMapActivity?extends?MapActivity?{
/**?Called?when?the?activity?is?first?created.?*/
private?MapController?mapController;
private?MapView?mapView;
private?MyOverLay?myOverLay;
@Override
public?void?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LocationManagerlocationManager=(LocationManager)?getSystemService(Context.LOCATION_SERVICE);
mapView=(MapView)?this.findViewById(R.id.mapview);
//設(shè)置交通模式
mapView.setTraffic(true);
//設(shè)置衛(wèi)星模式
mapView.setSatellite(false);
//設(shè)置街景模式
mapView.setStreetView(false);
//設(shè)置縮放控制
mapView.setBuiltInZoomControls(true);
mapView.setClickable(true);
mapView.setEnabled(true);
//得到MapController實(shí)例
mapController=mapView.getController();
mapController.setZoom(15);
myOverLay=newMyOverLay();
ListoverLays=mapView.getOverlays();
overLays.add(myOverLay);
Criteriacriteria=newCriteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(false);
criteria.setPowerRequirement(Criteria.POWER_LOW);
//取得效果最好的Criteria
Stringprovider=locationManager.getBestProvider(criteria,?true);
//得到Location
Locationlocation=locationManager.getLastKnownLocation(provider);
updateWithLocation(location);
//注冊一個(gè)周期性的更新,3秒一次
locationManager.requestLocationUpdates(provider,?3000,?0,?locationListener);
}
@Override
public?boolean?onCreateOptionsMenu(Menu?menu)?{
//?TODO?Auto-generated?method?stub
menu.add(0,?1,?1,?"交通模式");
menu.add(0,2,2,"衛(wèi)星模式");
menu.add(0,3,3,"街景模式");
return?super.onCreateOptionsMenu(menu);
}
@Override
public?boolean?onOptionsItemSelected(MenuItem?item)?{
//?TODO?Auto-generated?method?stub
super.onOptionsItemSelected(item);
switch?(item.getItemId())?{
case?1://交通模式
mapView.setTraffic(true);
mapView.setSatellite(false);
mapView.setStreetView(false);
break;
case?2://衛(wèi)星模式
mapView.setSatellite(true);
mapView.setStreetView(false);
mapView.setTraffic(false);
break;
case?3://街景模式
mapView.setStreetView(true);
mapView.setTraffic(false);
mapView.setSatellite(false);
break;
default:
mapView.setTraffic(true);
mapView.setSatellite(false);
mapView.setStreetView(false);
break;
}
return?true;
}
private?void?updateWithLocation(Location?location){
if(location!=null){
//為繪制類設(shè)置坐標(biāo)
myOverLay.setLocation(location);
GeoPointgeoPoint=newGeoPoint((int)(location.getLatitude()*1E6),?(int)(location.getLongitude()*1E6));
//定位到指定的坐標(biāo)
mapController.animateTo(geoPoint);
mapController.setZoom(15);
}
}
private?final?LocationListenerlocationListener=newLocationListener()?{
@Override
public?void?onStatusChanged(String?provider,?int?status,?Bundle?extras)?{
//?TODO?Auto-generated?method?stub
}
@Override
public?void?onProviderEnabled(String?provider)?{
//?TODO?Auto-generated?method?stub
}
@Override
public?void?onProviderDisabled(String?provider)?{
//?TODO?Auto-generated?method?stub
}
//當(dāng)坐標(biāo)改變時(shí)出發(fā)此函數(shù)
@Override
public?void?onLocationChanged(Location?location)?{
//?TODO?Auto-generated?method?stub
updateWithLocation(location);
}
};
class?MyOverLay?extends?Overlay{
private?Location?location;
public?void?setLocation(Location?location){
this.location=location;
}
@Override
public?boolean?draw(Canvas?canvas,?MapView?mapView,?boolean?shadow,
long?when)?{
//?TODO?Auto-generated?method?stub
super.draw(canvas,?mapView,?shadow);
Paintpaint=newPaint();
PointmyScreen=newPoint();
//將經(jīng)緯度換成實(shí)際屏幕的坐標(biāo)。
GeoPointgeoPoint=newGeoPoint((int)(location.getLatitude()*1E6),?(int)(location.getLongitude()*1E6));
mapView.getProjection().toPixels(geoPoint,?myScreen);
paint.setStrokeWidth(1);
paint.setARGB(255,?255,?0,?0);
paint.setStyle(Paint.Style.STROKE);
Bitmapbmp=BitmapFactory.decodeResource(getResources(),?R.drawable.mypicture);
//把這張圖片畫到相應(yīng)的位置。
canvas.drawBitmap(bmp,?myScreen.x,?myScreen.y,paint);
canvas.drawText("天堂沒有路",?myScreen.x,?myScreen.y,?paint);
return?true;
}
}
@Override
protected?boolean?isRouteDisplayed()?{
//?TODO?Auto-generated?method?stub
return?false;
}
@Override
public?boolean?onKeyDown(int?keyCode,?KeyEvent?event)?{
//?TODO?Auto-generated?method?stub
if?(keyCode==?KeyEvent.KEYCODE_BACK)?{
AlertDialog.Builderbuilder=newAlertDialog.Builder(this);
builder.setMessage("你確定退出嗎?")
.setCancelable(false)
.setPositiveButton("確定",
new?DialogInterface.OnClickListener()?{
public?void?onClick(DialogInterface?dialog,
int?id)?{
MyMapActivity.this.finish();
android.os.Process
.killProcess(android.os.Process
.myPid());
android.os.Process.killProcess(android.os.Process.myTid());
android.os.Process.killProcess(android.os.Process.myUid());
}
})
.setNegativeButton("返回",
new?DialogInterface.OnClickListener()?{
public?void?onClick(DialogInterface?dialog,
int?id)?{
dialog.cancel();
}
});
AlertDialogalert=builder.create();
alert.show();
return?true;
}
return?super.onKeyDown(keyCode,?event);
}
}
接下來看一下運(yùn)行后效果:

可以放大縮?。?/p>

可是使用menu鍵,切換不同的模式:

上面是切換到了衛(wèi)星模式。由于地圖需要耗費(fèi)大量的網(wǎng)絡(luò)資源,如果網(wǎng)絡(luò)比較慢的話會等待很長時(shí)間。
歡迎加技術(shù)學(xué)習(xí)交流群:364595326