lab 2-3 android google maps.ppt...
TRANSCRIPT
車輛定位與電子地圖整合服務車輛定位與電子地圖整合服務定位與Google Maps定位與Google Maps
Network Optimization LabNetwork Optimization LabDepartment of Computer ScienceNational Chiao Tung Universityg y
1
定位與Google Maps定位與Google Maps
Lab簡介:路徑軌跡記錄程式
G l M 程式技巧 Google Maps程式技巧
取得目前位置經緯度 取得目前位置經緯度
建立Google Maps
標示目前位置 標示目前位置
Marker的使用使
畫直線
實習時間 實習時間
2
Lab簡介:路徑軌跡記錄程式Lab簡介 路徑軌跡記錄程式
Google Maps程式技巧
取得目前位置經緯度 取得目前位置經緯度
建立Google Maps
標示目前位置
Marker的使用 Marker的使用
畫直線
成果展示。
在eclipse中import本次課程範例專案GoogleMap 然 在eclipse中import本次課程範例專案GoogleMap,然後執行程式。
3
模擬GPS輸入模擬GPS輸入
Emulator並不是真正的手機,因此無法收得手機,因此無法收得GPS訊號。
使用Emulator來模擬GPS輸入輸
在eclipse中點選 Window -> Show View -> Other-> Show View -> Other...
點選Android -> Emulator Control 然後按OK
剛開啟程式 無 GPS訊號
Control,然後按OK。
剛開啟程式,無 GPS訊號 ,無法記錄軌跡。 4
手動輸入GPS經緯度手動輸入GPS經緯度
在Location Controls中輸入經緯度
Longitude: Latitue: 點選Send。
Emulator就會接收到輸入的GPS位置。
5
程式技巧:取得目前位置經緯度程式技巧 取得目前位置經緯度
於AndroidManifest.xml註冊服務
ACCESS FINE LOCATION ACCESS_FINE_LOCATION
ACCESS COARSE LOCATION ACCESS_COARSE_LOCATION
位置程式碼的撰寫
宣告及取得系統服務
申請及移除週期性回報位置 申請及移除週期性回報位置
Location Listener Location Listener
6
於AndroidManifest.xml註冊服務於AndroidManifest.xml註冊服務
於<manifest>標籤底下註冊
ACCESS FINE LOCATION ACCESS_FINE_LOCATION
許可程式可獲得存取精確位置(GPS) ACCESS_COARSE_LOCATION
許可程式可獲得存取不精確位置(基地台)存 精
7
宣告及取得系統服務宣告及取得系統服務
Import
變數宣告變數宣告
取得系統服務
取得系統最近獲得的位置獲得的位置
8
程式碼解說程式碼解說
mgr = (LocationManager)getSystemService(LOCATION_SERVICE);
利用Context類別的getSystemService取得Location Manager的物 利用Context類別的getSystemService取得Location Manager的物件實體。
Criteria criteria = new Criteria(); best = mgr.getBestProvider(criteria, true);
Android 系統會有多個定位提供者,Criteria類別是用來讓開發者設定其對定位提供者的偏好(如省電考 )定其對定位提供者的偏好(如省電考量)。
mgr.getBestProvider()根據Criteria物件的內容, 回傳最符合開發者偏好的定位提供者 回傳為值String type 代表provider的名稱偏好的定位提供者 ,回傳為值String type,代表provider的名稱。
public Location getLastKnownLocation (String provider)
根據開發者所傳入的provider,來回傳出此provider最近獲得的位置。
9
申請及移除週期性回報位置申請及移除週期性回報位置
申請週期性位置Update位置Update
移除週期性 移除週期性位置Update
10
程式碼解說程式碼解說
public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener g , ,listener);
申請週期性的提供位置資訊。 申請週期性的提供位置資訊。
provider: 位置提供者
minTime: 位置更新的最短間隔時間 minTime: 位置更新的最短間隔時間
minDistance: 位置更新的最短距離(單位:公尺)
listener: 用來負責傾聽處理位置變化的訊息 listener: 用來負責傾聽處理位置變化的訊息
public void removeUpdates(LocationListener listener);
移除週期性的提供位置資訊 移除週期性的提供位置資訊 。
11
Location ListenerLocation Listener
Listener的實體
用來負責傾聽處理位置變化的訊息
Li t 的四個必要函式 Listener的四個必要函式
public void onLocationChanged(Location location) { }
Called when the location has changed.
public void onProviderDisabled(String provider) { }
Called when the provider is disabled by the user.
public void onProviderEnabled(String provider) { }provider) { }
Called when the provider is enabled by the user.
public void onStatusChanged(String p g ( gprovider, int status, Bundle extras) { }
Called when the provider status changes.
12
練習1 - 取得目前位置經緯度 (1/2)M if t檔Manifest檔
將一列程式碼貼到檔AndroidManifest.xml檔。
<?xml version="1.0" encoding="utf‐8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
k " d d id l "package="com.demo.android.GoogleMap"android:versionCode="1"android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".GoogleMap"android:label="@string/app_name">
<intent‐filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" />
</intent‐filter></activity>
</application><uses‐permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses‐permission><uses‐permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses‐permission></manifest>
13
練習1 - 取得目前位置經緯度 (2/2)J C dJava Code
private LocationManager mgr;private String best;////////////////////////////////////////////////////////////////////////////////////////////////////////////////@Override
public void onCreate(Bundle savedInstanceState) {
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {// TODO Auto-generated method stubpublic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);setContentView(R.layout.main);mgr = (LocationManager)getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria();best = mgr.getBestProvider(criteria, true);
// TODO Auto generated method stubToast.makeText(GoogleMap.this, "Latitude : " +
location.getLatitude() + " , Longitude : " + location.getLongitude(), Toast.LENGTH_LONG).show();
//loc.setText("Latitude : " + location.getLatitude() + " , Longitude : " + location.getLongitude());g g ( , );
Location location = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (best != null){
location = mgr.getLastKnownLocation(best);
}
public void onProviderDisabled(String provider) {// TODO Auto-generated method stub
}Toast.makeText(this, "Latitude : " + location.getLatitude() + " ,
Longitude : " + location.getLongitude(), Toast.LENGTH_LONG).show();}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
public void onProviderEnabled(String provider) {// TODO Auto-generated method stub
}@Overrideprotected void onResume(){mgr.requestLocationUpdates("gps", 2000, 1, locationListener);
super.onResume();}
}
public void onStatusChanged(String provider, int status,Bundle extras) {
// TODO Auto-generated method stub
////////////////////////////////////////////////////////////////////////////////////////////////////////////////@Override
protected void onStop(){mgr.removeUpdates(locationListener);super.onStop();
}
};
14
}
程式技巧:建立Google Maps程式技巧 建立Google Maps
申請Google Maps開發金鑰。鑰。
於androidManifest.xml註冊服務。
/res/layout/main xml的撰 /res/layout/main.xml的撰寫。
地圖程式碼的撰寫。
建立Google Map 15
STEP 1:取得Keystore位置STEP 1 取得Keystore位置
開發的金鑰與import到機器的金鑰不同。
產生認證指紋<MD5>。 產生認證指紋 MD5 eclipse點選Windows->Preferences,取得keystore位置。
打開cmd進到keystore的目錄底下。
16
STEP 2:產生認證指紋MD5STEP 2 產生認證指紋MD5
在cmd中,進入到放置key的目錄底下。
執行:keytool -list -keystore debug.keystore執行 keytool list keystore debug.keystore 輸入密碼:android,以取得MD5。
若發生’keytool’不是內部或外部指令時,請按照下 若發生 keytool 不是內部或外部指令時 請按照下張投影片所述,請進到keytool目錄底下執行。
17
發生Keytool不是內部或外部命令時發生Keytool不是內部或外部命令時
進到keytool所在的目錄(通常在Java的目錄底下) ,執行:執行keytool –list –keystore C:\Users\使用者名稱\.android\debug.keystore
18
STEP 3:申請Google Map開發金鑰STEP 3 申請Google Map開發金鑰
使用Browser連線http://code.google.com/intl/zh-TW/android/maps-api-signup.html
在網頁中輸入剛剛取得的MD5,選項勾選完在點選Generate API Key。
19
STEP 4:取得Android Maps API KeySTEP 4 取得Android Maps API Key
20
於androidManifest.xml註冊服務於androidManifest.xml註冊服務
打開androidManifest.xml,加入下二行:
使用google map library(application tag內加入)。使用google map library(application tag內加入)。
允許程式可以連結到internet 。
21
/res/layout/main.xml的撰寫/res/layout/main.xml的撰寫
於main.xml中layout內加入此行,放置Google Map的位置的位
其中0T_6-yJ7B0oMii0kyiLxe5_y2zUjQwKemdcHPUg為剛剛申請的API key申請的API key
android:clickable=”true”代表設定Map可拖曳
22
地圖程式碼:宣告及設定地圖程式碼 宣告及設定
import data
extends Mapactivity
宣告Map variable 宣告Map variable
設定Map設定 p
23
地圖程式碼:MapActivity地圖程式碼 MapActivity
Mapactivity必要實作此函式
eclipse可以點選implement此函式p p
24
程式碼解說 (1/2)程式碼解說 (1/2)
public class test extends MapActivity
繼承MapActivity,當中其實作一些顯示MapView的必要程式 繼承MapActivity 當中其實作 些顯示MapView的必要程式碼。
map = (MapView)findViewById(R.id.map);p ( p ) y ( p); 讓變數map取得MapView位置,也就是在main.xml中設定的位置。
mc = map.getController();
取得這個MapView的MapController物件。 取得這個MapView的MapController物件
mc.setZoom(int zoomLevel);
愈接近 顯 的區域愈大 資料 1<=zoomLevel<=21,愈接近1顯示的區域愈大,資料愈粗略;反之,則相反。
25
程式碼解說 (2/2)程式碼解說 (2/2)
map.setSatellite(true);
是否顯示衛星影像。 是否顯示衛星影像。
map.setBuiltInZoomControls(true);
是否內建zoom control。MapController animateTo(GeoPoint point) MapController.animateTo(GeoPoint point)
設定map的中心位置。
GeoPoint(int latitudeE6, int longitudeE6)
設定坐標點 其經緯度為integer型態 大小為 設定坐標點,其經緯度為integer型態,大小為一般的經緯度 * 106。
26
練習2 - 建立Google Maps (1/2)M if t及 i lManifest及main.xml
Manifest的撰寫 main.xml的撰寫<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo.android.GoogleMap"android:versionCode="1"android:versionName="1.0">
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"android:layout_height="fill_parent">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<uses-library android:name = "com.google.android.maps"/><activity android:name=".GoogleMap"
android:label="@string/app_name">
<com.google.android.maps.MapViewandroid:id="@+id/map"android:layout_width="fill_parent"android:layout_height="fill_parent"
<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" />
</intent-filter></activity>
/
android:apiKey="0T_6-yJ7B0oNorQXRUE_e6kc3dMuTW0RaAoSEng"android:clickable="true"/><LinearLayout android:id="@+id/zoom"
android:layout_width="wrap_content"</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission><uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"></uses permission>
android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"
/><TextView android:id="@+id/loc"
</uses-permission><uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
</manifest>
android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/>
</RelativeLayout>
27
練習2 - 建立Google Maps (2/2)J C dJava Code
public class GoogleMap extends MapActivity{ :
private MapView map;private MapController mc;private LocationManager mgr;p g gprivate String best;
://create Google Maps
private void showMaps() { map = (MapView)findViewById(R.id.map);( ) y ( )mc = map.getController();mc.setZoom(19);Criteria criteria = new Criteria();best = mgr.getBestProvider(criteria, true);Location location = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);if (best != null){
location = mgr.getLastKnownLocation(best);}if (location != null){
mc.animateTo(new GeoPoint((int)(location.getLatitude()*1000000), (int)(location.getLongitude()*1000000)));}else{
mc.animateTo(new GeoPoint((int)(24.78640079498291*1000000), (int)(120.99709331989288*1000000)));}map.setSatellite(true);map.setBuiltInZoomControls(true);
}
28
程式技巧:標示目前位置程式技巧 標示目前位置
在Google Maps上自動定位自己的位置,且顯示出位自己的位置 且顯示出自定的位置圖片。
申請週期性位置服務 申請週期性位置服務
MyLocationOverlayer的使用的使用
圖層的取得及使用 圖層的取得及使用
取得新位置時的反應
定位到自己位置顯示腳
定位圖示
定位到自己位置顯示腳印圖片 29
申請週期性位置服務申請週期性位置服務
變數宣告
註冊位置update
移除位置update
30
MyLocationOverlayer的使用MyLocationOverlayer的使用
取得map的圖層
設定位置改變時的行為
將圖層mylayer載入到map上
31
圖層的取得及使用圖層的取得及使用
List<Overlay> overlays;
宣告 個li t物件 裡面用來放置圖層 宣告一個list物件,裡面用來放置圖層。
overlays = map.getOverlays();y p g y ();
取得目前map的圖層。
O ( ) mylayer = new MyLocationOverlayer(this, map);
宣告一個圖層物件。 宣告 個圖層物件
overlays.add(mylayer);
將剛剛宣告的圖層物件載入至map上。
32
新位置事件處理程序新位置事件處理程序
mylayer.runOnFirstFix(new Runnable() {new Runnable() { public void run() { mc animateTo(mylayer getMyLocation());mc.animateTo(mylayer.getMyLocation());
} } );
其參數為一Runnable物件,當位置改變時,系統會自動產生一個thread去此Runnable物件的內統會自動產生 個thread去此Runnable物件的內容。
33
預設的定位圖示預設的定位圖示
將myLocationOverlayer class繼承class繼承MyLocationOverlay class。
MyLocationOverlay class內有drawMyLocation函式,有 y 函式可用來繪製mylocation的圖形。形
預設的圖示:
34
自定定位圖示自定定位圖示
• Override繼承到的MyLocationOverlay class內drawMyLocation函式。drawMyLocation函式。
預設定位圖示 自定定位圖示預設定位圖示 自定定位圖示35
顯示位置的程式碼顯示位置的程式碼
extends MylocationOverlay
Draw mylocation
36
使用Drawable類別使用Drawable類別
Drawable drawable;
宣告 個d bl 物件 此類別可用來設定及存放繪 宣告一個drawable物件,此類別可用來設定及存放繪製的圖形,將圖形繪製到Canvas(畫布)上。
drawable = mapView.getContext().getResources().getDrawp g () g () gable(R.drawable.north1);
取得要繪製的圖形 取得要繪製的圖形。
width = drawable.getIntrinsicWidth(); g ()
取得圖形的寬度 。
37
將目前位置投影到手機螢幕的地圖上將目前位置投影到手機螢幕的地圖上
height = drawable.getIntrinsicHeight();取得圖形高度。 取得圖形高度。
Point center = new point(); 宣告一point物件,其用來存放螢幕的像素座標。
Projection projection = Projection projection mapView.getProjection();
取得目前地圖座標投影到螢幕的投影 取得目前地圖座標投影到螢幕的投影。
projection.toPixels(myLoc, center); 將目前位置myLoc投影到center上。
38
Canvas(畫布)及Drawable圖形邊界設定邊界設定
Canvas canvas為一畫布物件。 為一畫布物件。
canvas.rotate(lastFix.getBearing(), center.x , t )center.y);
旋轉目前的畫布,lastFix為目前位置的前一個位置。
旋轉角度由gps的bearing提供。
drawable setBounds(center x - width / 2 drawable.setBounds(center.x - width / 2, center.y - height / 2, center.x + width / 2, center y + height / 2);center.y + height / 2); 設定邊界。
39
將圖示繪製到Canvas上將圖示繪製到Canvas上
drawable.draw(canvas);
將圖形繪製到畫布上 將圖形繪製到畫布上。
修改完成後,顯示位置中修改完成後 顯示位置中心便會更改成我們要的圖形。形
40
練習3 - 標示目前位置J dJava code
public class MyLocationOverlayer extends MyLocationOverlay {
private Drawable drawable;private Point center;private int width;
private MyLocationOverlayer mylayer;private List<Overlay> overlays;
////////////////////////////////////////////////////////////////////////////////////////////
private int height;private int counter = 0;
public MyLocationOverlayer(Context context, MapView mapView) { super(context, mapView);
}
@Overrideprotected void onResume(){
mylayer.enableMyLocation();super.onResume();
}@Override }
@Override protected void drawMyLocation(Canvas canvas, MapView
mapView, Location lastFix, GeoPoint myLoc, long when) {
if (counter++ %2 == 0)drawable =
@protected void onStop(){
mylayer.disableMyLocation();super.onStop();
}
////////////////////////////////////////////////////////////////////////////////////////////mapView.getContext().getResources().getDrawable(R.drawable.north1);
elsedrawable =
mapView.getContext().getResources().getDrawable(R.drawable.north2);width = drawable.getIntrinsicWidth(); height = drawable.getIntrinsicHeight();
private void localBaseService(){
overlays = map.getOverlays();mylayer = new MyLocationOverlayer(this, map);mylayer.runOnFirstFix( height drawable.getIntrinsicHeight();
center = new Point(); Projection projection = mapView.getProjection(); projection.toPixels(myLoc, center);
//emulator 不提供getBearing(),但實機上會提供canvas rotate(lastFix getBearing() center x center y);
mylayer.runOnFirstFix(new Runnable() { public void run() {
mc.animateTo(mylayer.getMyLocation());
}});overlays add(mylayer); canvas.rotate(lastFix.getBearing(), center.x , center.y);
drawable.setBounds(center.x - width / 2, center.y - height / 2, center.x + width / 2, center.y + height / 2);
drawable.draw(canvas);canvas.rotate(-lastFix.getBearing(), center.x , center.y);
}
overlays.add(mylayer);}
}}
41
程式技巧:Marker的使用程式技巧 Marker的使用
• Maker的主要功能在於….在map上秀出Marker點選在map上秀出Marker點選下去產生反應
42
MarkerOverlay類別的使用MarkerOverlay類別的使用
宣告MarkerOverlay物件
傳入一Drawable物件與Context物件當作contructor參數
將MarkerOverlay載入到Map
43
MarkerOverlay類別的撰寫MarkerOverlay類別的撰寫
44
繼承ItemizedOverlay繼承ItemizedOverlay
extends ItemizedOverlay其需要一個OverlayItem的串列。
宣告一個ArrayList類別產生這個動態串列
BoundCenterBottom用來調整Drawable物件的邊界
清空list
增加item到list裡,OverlayItem constructor需要三個參數
1 景點位置的G P i t 2 景點標題 3 景點的片段說明1.景點位置的GeoPoint;2.景點標題;3.景點的片段說明。
45
建立景點圖示及點選時的反應建立景點圖示及點選時的反應
執行populate(),其會呼叫createItem() ,如呼叫 () 如此才能真正建立景點圖示。
用來處理當景點被按下時產生的反應。
46
練習4 - Marker的使用J C dJava Code
private MarkerOverlay markerOverlay;private List<Overlay> overlays;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MarkerOverlay extends ItemizedOverlay<OverlayItem> {Context mCtx;
private List<OverlayItem> items = new ArrayList<OverlayItem>();public MarkerOverlay(Drawable defaultMarker Context mCtx) {private void localBaseService()
{Drawable drawable;drawable = getResources().getDrawable(R.drawable.location);markerOverlay = new MarkerOverlay(drawable,this);overlays.add(markerOverlay);
}
public MarkerOverlay(Drawable defaultMarker,Context mCtx) {super(boundCenterBottom(defaultMarker));this.mCtx = mCtx;items.clear();items.add(new OverlayItem(new
GeoPoint((int)(24.78660079498291*1E6),(int)(120.99709331989288*1E6)), "POINT 1" null));} POINT 1 , null));
populate();}
@Overrideprotected OverlayItem createItem(int i) {{
return items.get(i);}
@Overridepublic int size(){{
return items.size();}
@Overrideprotected boolean onTap(int pIndex){{
Toast.makeText(mCtx, "Here is " + items.get(pIndex).getTitle(), Toast.LENGTH_SHORT).show();
return true;}
}
47
程式技巧:畫直線程式技巧 畫直線
• 在Map上繪製一條線
M O l 類別的宣告及使• MyOverlay類別的宣告及使用
• 繼承Overlay類別
• Paint類別的使用Paint類別的使用
48
MyOverlay類別的宣告及使用MyOverlay類別的宣告及使用
宣告MyOverlay物件
執行其constructor並載執行其 載入到Map上
MyOverlay類別
49
繼承Overlay類別繼承Overlay類別
Extends Overlay類別
O id d th d Override draw method
50
Paint類別的使用Paint類別的使用
宣告Paint物件
此類別用來設定畫筆的參數 此類別用來設定畫筆的參數
設定畫筆的參數
setColor:設定顏色
setStrokeWidth:設定筆畫寬度
setAlpha:設定顏色的深淺
在canvas上畫線,從點1到點2 在canvas上畫線 從點1到點2 參數1、2為點1的x,y像素值,參數2,3為點2的x,y像素值,參數5為使用的畫筆值 參數5為使用的畫筆
51
練習5 - 畫直線J C dJava Code
private List<Overlay> overlays;private MyOverlay line;private Location point1, point2;
class MyOverlay extends Overlay{
private Paint mPaint;private Location myLocation, point1, point2;
///////////////////////////////////////////////////////////////////////////////////////////////////
overlays = map.getOverlays();line = new MyOverlay(point1, point2); overlays.add(line);
p y p ppublic MyOverlay(Location point1, Location point2){
this.point1 = new Location(point1);this.point2 = new Location(point2);
}@Override@public void draw(Canvas canvas, MapView mapv, boolean shadow){
Projection projection = mapv.getProjection(); mPaint = new Paint();mPaint.setColor(Color.RED);C (C );mPaint.setStrokeWidth(5);mPaint.setAlpha(120);
Point p1 = new Point();Point p2 = new Point();projection.toPixels(new GeoPoint((int)(point1.getLatitude()*1E6),projection.toPixels(new GeoPoint((int)(point1.getLatitude() 1E6),
(int)(point1.getLongitude()*1E6)), p1);projection.toPixels(new GeoPoint((int)(point2.getLatitude()*1E6),
(int)(point2.getLongitude()*1E6)), p2);
canvas.drawLine(p1.x, p1.y, p2.x,p2.y, mPaint);
} // end draw
} // end class
52