Android Google Maps 建國科技大學 資管系 饒瑞佶 2012/4 經濟部工業局 Android...
-
Upload
wendy-lang -
Category
Documents
-
view
237 -
download
3
Transcript of Android Google Maps 建國科技大學 資管系 饒瑞佶 2012/4 經濟部工業局 Android...
Android Google Maps
建國科技大學 資管系饒瑞佶2012/4
經濟部工業局Android 智慧型手機程式設計實務應用班
Google Maps
• 取得 Google Map API
Step1: 先進入 JDK 目錄
Reference :http://developer.android.com/resources/tutorials/views/hello-mapview.html
Google Maps
• 透過 keytool.exe 建立認證指紋• 需要 debug_keystore 路徑
Google Maps• debug_keystore 路徑
Google Maps• 輸入 keytool –list –alias androiddebugkey –keystore
“C:\Documents and Settings\Administrator\.android\debug.keystore” –storepass android –keypass android
Google Maps
• 產生認證指紋
Google Maps
• 進入 Google Map API Key 申請頁面• http://code.google.com/intl/zh-Tw/android/
add-ons/google-apis/maps-api-signup.html
輸入認證指紋碼
Google Maps
• 進入 Google Map API Key 申請頁面• http://code.google.com/intl/zh-Tw/android/
add-ons/google-apis/maps-api-signup.html
Google Maps
• 產生出 API 金鑰
<com.google.android.maps.MapView android:layout_width="fill_parent" android:layout_height="fill_parent" android:apiKey="0O7bGO2vQxBc90bpYbJ8PnSjJapePPkrSGRvP3A" />
0O7bGO2vQxBc90bpYbJ8PnSjJapePPkrSGRvP3A
加入 main.xml
Google Maps
main.xml
Google Maps• 建立新專案 : HelloMaps
沒有 Google APIs target
Google Maps• 如果沒有 Google APIs target• 請選擇 Available packages 進行安裝
Google Maps• 安裝完 Google APIs target 畫面
Google Maps
• 建立新專案 : HelloMaps
顯示 Google Maps 地圖
改成 MapActivity
加入
加入
Google Maps
• AVD 也要對應具備 Google APIs 功能
Google Maps• 增加 <uses-permission
android:name="android.permission.INTERNET" />• 在 <application> 裡頭增加 <uses-library
android:name="com.google.android.maps" /> 資訊
Google Maps
在 Google Maps 上加標示• 需要一個 overlay class ,做堆疊圖層之用
MapsOverlayimport java.util.ArrayList;import android.app.AlertDialog;import android.content.Context;import android.graphics.drawable.Drawable;import com.google.android.maps.ItemizedOverlay;import com.google.android.maps.OverlayItem;
public class MapsOverlay extends ItemizedOverlay<OverlayItem> { private ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>(); private Context context; public MapsOverlay(Drawable defaultMarker) { super(boundCenterBottom(defaultMarker)); } public MapsOverlay(Drawable defaultMarker, Context context) { this(defaultMarker); this.context = context; }
@Override protected OverlayItem createItem(int i) { return mapOverlays.get(i); }
@Override public int size() { return mapOverlays.size(); } @Override protected boolean onTap(int index) { OverlayItem item = mapOverlays.get(index); AlertDialog.Builder dialog = new AlertDialog.Builder(context); dialog.setTitle(item.getTitle()); dialog.setMessage(item.getSnippet()); dialog.show(); return true; } public void addOverlay(OverlayItem overlay) { mapOverlays.add(overlay); this.populate(); }
}
Main.xml
加入這段來切換地圖種類
決定地圖能不能互動
決定 View 顯示方式需要與 layout_width 或layout_height 一起使用
layout_weight
改變看看
改變看看
改變看看
改變看看
改變看看
改變看看
HelloMaps給定一個座標 ( 未來可以來自於 GPS)
在給定座標上加圖示
圖示坐標
圖示按下時顯示的資訊
切換成衛星圖
切換成標準地圖
試試改變圖示
地址轉座標try { inputaddress=(EditText)findViewById(R.id.editText1); Geocoder geocoder = new Geocoder(Maps1Activity.this, Locale.getDefault()); List<Address> geoResults = geocoder.getFromLocationName(inputaddress.getText().toString(), 5); while (geoResults.size()==0) { geoResults = geocoder.getFromLocationName(inputaddress.getText().toString(), 5); } if (geoResults.size()>0) { Address addr = geoResults.get(0); Double latitude = addr.getLatitude() * 1E6; Double longitude = addr.getLongitude() * 1E6; tv1.setText(latitude + "/" + longitude); showlocation((int) (addr.getLatitude() * 1E6),(int) (addr.getLongitude() * 1E6));
}} catch (Exception e) { tv1.setText("convert error");}
AVD 多數執行有問題,最好使用手機測試1600 Amphitheatre Parkway, Mountain View, CA
Android 2.2
輸入地址
轉換地址成座標
座標
顯示座標點
不用註冊 Google Maps API 也可以使用 Intent
利用 Intent 玩 Google Maps
• 建立新專案 : IntentMaps
顯示 Google Maps 地圖
要取消
利用 Intent 玩 Google Maps
• AVD 也要對應具備 Google APIs 功能
利用 Intent 玩 Google Maps
• 增加 <uses-permission android:name="android.permission.INTERNET" />
利用 Intent 玩 Google Maps
更多 Google Maps– Google Maps
URI 格式 :
geo:latitude,longitude << 沒有小圖示 geo:0,0?q=latitude,longitude << 出現圖示
geo:latitude,longitude?z=zoom << 目前沒作用geo:0,0?q=my+street+address << 出現有註冊的位置 (my已取消 )geo:0,0?q=business+near+city
– Google Streetview
URI 格式 :
google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom
Uri uri=Uri.parse("google.streetview:cbll=46.813812,-71.207378&cbp=1,99.56,,1,-5.27&mz=21");
只支援美加地區
更多 Google Maps
• 顯示地圖
Uri uri = Uri.parse("geo:38.899533,-77.036476"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it);
• 路徑規劃
Uri uri = Uri.parse("http://maps.google.com/maps? f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it);
//where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456
GPS
AndroidManiFest.xml
• 需要開放以下權限– <uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
– <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
建立一個新專案 HelloGPS
偵測是否開啟 GPS
// 如果沒有開啟 GPS---------------------
LocationManager status=(LocationManager)(this.getSystemService(Context.LOCATION_SERVICE));
if(status.isProviderEnabled(LocationManager.GPS_PROVIDER) || status.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
}else{
// 到系統開啟 GPS 與 WIFI 服務的畫面 startActivity(new
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
//-------------------- 如果沒有開啟 GPS
Android GPS 運作方式• 取得 LocationManager :判定是否有提供定
位服務 ( 硬體 GPS 或 WIFI)• 建立 LocationProvider ,設定定位參數,並
同時透過 LocationManager 取得座標 ( 硬體軟體, GPS 或是 WiFi)
• 設定 LocationManager 的 Listener 事件,偵測事件的改變
• MapController 負責控制 Google Maps
GPS 訊號抓取主體
沒有 GPS時觸發
GPS 訊號擷取主體
宣告
mLocationManager =(LocationManager)(this.getSystemService(Context.LOCATION_SERVICE)); if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){ }else{ // 到達系統開啟 GPS 與 WIFI 服務的畫面 startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); } //-------------------- 如果沒有開啟 GPS /* Provider 初始化 */ getLocationPrivider(); /* 設定事件的 Listener */ mLocationManager.requestLocationUpdates(mLocationPrivider, 2000, 0, mLocationListener); if(mLocation!=null) // 第一次顯示 { // 取得速度 double speed=mLocation.getSpeed()/1000*60*60; //原單位是 m/s double altitude = mLocation.getAltitude(); tv_show_gps.setText(" 緯度: " + formatgeo(mLocation.getLatitude()) + " 經度: " + formatgeo(mLocation.getLongitude()) + " 海拔: " + altitude + " m 速度: " + formatspeed(speed) + "km/h"); }
啟動 GPS
如果沒有啟動使用 GPS 服務,將跳至設定畫面
要求 GPS 提供服務設定 GPS 監聽服務
如果有 GPS 訊號,顯示到畫面上
TextView tv_show_gps;
private ProgressDialog MyDialog;private LocationManager mLocationManager;private String mLocationPrivider="";private Location mLocation;
宣告物件
// 取得 LocationProviderpublic void getLocationPrivider(){ Criteria mCriteria01 = new Criteria(); mCriteria01.setAccuracy(Criteria.ACCURACY_FINE); mCriteria01.setAltitudeRequired(true); //需要高度 mCriteria01.setBearingRequired(false); mCriteria01.setCostAllowed(true); mCriteria01.setPowerRequirement(Criteria.POWER_LOW); mLocationPrivider = mLocationManager.getBestProvider(mCriteria01, true); mLocation = mLocationManager.getLastKnownLocation(mLocationPrivider);}
// 偵測位置改變public final LocationListener mLocationListener = new LocationListener(){ public void onLocationChanged(Location location) { // 如果記錄進行中,就畫路線並更新移動距離 // 取得速度 double speed=location.getSpeed()/1000*60*60; //原單位是m/s double altitude = location.getAltitude(); tv_show_gps.setText(" 緯度: " + formatgeo(location.getLatitude()) + " 經度: " + formatgeo(location.getLongitude()) + " 海拔: " + altitude + " m 速度: " + formatspeed(speed) + "km/h"); MyDialog.dismiss(); // 結束進度 } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider,int status,Bundle extras) { }};//----------------- 偵測位置改變
// 產生定位中視窗 private void createCancelProgressDialog(String title, String message, String buttonText) { MyDialog = new ProgressDialog(this); MyDialog.setTitle(title); MyDialog.setMessage(message); MyDialog.setButton(buttonText, new DialogInterface.OnClickListener(){ public void onClick(DialogInterface dialog, int which){ // Use either finish() or return() to either close the activity or just the dialog android.os.Process.killProcess(android.os.Process.myPid()); HelloGPSActivity.this.finish(); return; } }); MyDialog.show(); // 顯示進度 }
// 按 BACK 按鍵時關閉程式@Overridepublic void onBackPressed() { android.os.Process.killProcess(android.os.Process.myPid()); HelloGPSActivity.this.finish(); }
// format GPS 座標的方法 public String formatgeo(double num){NumberFormat formatter = new DecimalFormat("###.####");String s=formatter.format(num);return s;}
// format speed 的方法 public String formatspeed(double num){NumberFormat formatter = new DecimalFormat("###.##");String s=formatter.format(num);return s;}
透過 ddms 送出模擬 GPS 座標到 AVD
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
GPS
• 取得 GPS 訊號後,將其顯示到 Google Maps 上,移動時,該點會移動– 抹除舊圖層,放上新的點
• 顯示成一個動態路徑– 將新的點加入原有圖層中,保留所有的點
• 將 GPS 座標記錄到 SQLite 資料庫,之後可以重新取回
取得 GPS 訊號後,將其顯示到Google Maps 上
onCreate 與宣告
MapView物件與圖層
MapView對應到圖層
清除圖層顯示座標點
gpsonmaps.xml
來自於Google
Maps 認證頁
LocationListener
清除圖層顯示座標點
showmaps 函數
負責在圖層上顯示 GPS 座標點
private void showmaps(Location location) { Drawable drawable=this.getResources().getDrawable(R.drawable.ic_launcher); MapsOverlay itemizedOverlay=new MapsOverlay(drawable,this); double geoLatitude = location.getLatitude()*1E6; double geoLongitude = location.getLongitude()*1E6; GeoPoint point=new GeoPoint((int) geoLatitude, (int) geoLongitude); OverlayItem overlayitem=new OverlayItem(point,"Hello","I'm in Athens, Greece!"); itemizedOverlay.addOverlay(overlayitem); mapOverlays.add(itemizedOverlay); MapController mapcontroller=mapView.getController(); mapcontroller.animateTo(point); mapcontroller.setZoom(18);}
最後!記得 Activity 要改成 MapActivity
取得 GPS 訊號後,將其顯示到Google Maps 上並畫出軌跡
從前個範例修改
產生 MyOverLay 類別import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.graphics.RectF;import com.google.android.maps.GeoPoint;import com.google.android.maps.MapView;import com.google.android.maps.Overlay;import com.google.android.maps.Projection;
public class MyOverLay extends Overlay {private GeoPoint gp1;private GeoPoint gp2;private int mRadius=10;private int mode=0;/* 建構子,傳入起點與終點的 GeoPoint 與 mode */public MyOverLay(GeoPoint gp1,GeoPoint gp2,int mode){ this.gp1 = gp1; this.gp2 = gp2; this.mode = mode;}
@Overridepublic boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when){Projection projection = mapView.getProjection();if (shadow == false){/* 設定筆刷 */Paint paint = new Paint();paint.setAntiAlias(true);paint.setColor(Color.BLUE); // 點的顏色Point point = new Point();projection.toPixels(gp1, point);
/* mode=1 :建立起點 */if(mode==1){ /* 定義 RectF 物件 */ RectF oval=new RectF(point.x - mRadius, point.y - mRadius, point.x + mRadius, point.y + mRadius); /* 繪製起點的圓形 */ canvas.drawOval(oval, paint);}/* mode=2 :畫路線 */else if(mode==2){ Point point2 = new Point(); projection.toPixels(gp2, point2); paint.setColor(Color.BLACK); // 中間路徑的顏色 paint.setStrokeWidth(5); paint.setAlpha(120); /* 畫線 */ canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);}/* mode=3 :建立終點 */else if(mode==3){ /* 避免誤差,先畫最後一段的路線 */ Point point2 = new Point(); projection.toPixels(gp2, point2); paint.setColor(Color.RED); // 結束點的顏色 paint.setStrokeWidth(5); paint.setAlpha(120); canvas.drawLine(point.x, point.y, point2.x,point2.y, paint); /* 定義 RectF 物件 */ RectF oval=new RectF(point2.x - mRadius,point2.y - mRadius, point2.x + mRadius,point2.y + mRadius); /* 繪製終點的圓形 */ paint.setAlpha(255); canvas.drawOval(oval, paint);}
}return super.draw(canvas, mapView, shadow, when);}}
變數// GPS 座標前後點GeoPoint gp1;GeoPoint gp2;MapController mapcontroller;boolean _run;
修改 onCreate
btn_streetview.setOnClickListener(new Button.OnClickListener() //strat{ @Override public void onClick(View arg0) { // TODO Auto-generated method stub try{ gp1=gp2; resetOverlay(); _run = true; refreshMapView(); setRoute(1); // 起點 }catch(Exception e){ } }}); btn_satellitetview.setOnClickListener(new Button.OnClickListener() //stop {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stub _run = false; setRoute(3); // 終點 refreshMapView();} });
/* 取得 GeoPoint 的方法 */private GeoPoint getGeoByLocation(Location location){ GeoPoint gp = null; try { if (location != null) { double geoLatitude = location.getLatitude()*1E6; double geoLongitude = location.getLongitude()*1E6; gp = new GeoPoint((int) geoLatitude, (int) geoLongitude); } }catch(Exception e){ e.printStackTrace(); } return gp;}
/* 更新 MapView 的方法 */public void refreshMapView(){ mapView.displayZoomControls(true); MapController myMC = mapView.getController(); myMC.animateTo(gp2); myMC.setZoom(18); mapView.setSatellite(false); //不用衛星地圖 mapView.setClickable(true); //設定地圖可以被選取移動}
/* 重設 Overlay 的方法 */private void resetOverlay(){ List<Overlay> overlays = mapView.getOverlays(); overlays.clear();}
/* 設定路線的方法 */private void setRoute(int mode){ MyOverLay mOverlay = new MyOverLay(gp1,gp2,mode); List<Overlay> overlays = mapView.getOverlays(); overlays.add(mOverlay);}
修改 LocationListener
修改 LocationListenerif(_run && iflocated){ gp2=getGeoByLocation(location);; setRoute(2); // 畫線 refreshMapView(); gp1=gp2;}else if(iflocated==false) { new AlertDialog.Builder(GPSLine.this) .setTitle(" 定位 ") .setMessage(" 定位完成,可以開始使用! ") .setPositiveButton(" 確認 ",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }) .show(); iflocated=true; MyDialog.dismiss();}