GOOGLE MAP 實習
學 校 :南開科技大學 系 所 :數位生活創意系 老 師 :林正敏教授 1
CRE@TAIWAN
智活 文創
Google MAP for GPS實習
Google MAP 簡介
Google地圖,前稱Google Local,是Google公司向全球 提供的電子地圖服務,包括局部詳細的衛星照片。 提供三種視圖: 向量地圖(傳統地圖),可提供政區和交通以及商業資訊
不同解析度的衛星照片(俯視圖,跟Google地球上的衛星照片基本一樣)
後來加上的地形圖,可以用以顯示地形和等高線。
Google MAP 簡介
• Google MAP 的姊妹產品是Google地球,一個電腦應用程式, 在3D地球模型上提供街景和更多的衛星視圖及GPS定位的 功能,但沒有向量視圖和地形視圖功能。 • 由於Google地圖是一項電子地圖服務,擁有比紙質地圖更 多的優越性,特別是近年來行動裝置的智慧化,網路速度 的提升,更是讓Google地圖與人們的生活產生更為緊密的 聯繫,因而倍受人們的讚譽。
開發工具
Eclipse Java jdk
Android – SDK
第零章
開發工具安裝
JAVA安裝
• jdk-6u18-windows-i586 點兩下安裝,持續按下一步即可 過程中都不用更動
JAVA安裝
• 設定環境變數 – 我的電腦→滑鼠右鍵→內容→進階→環境變數
JAVA安裝
• 在系統變數欄裡找 Path (如下圖),點選編輯
JAVA安裝
• 再到JAVA的安裝目錄裡找bin資料夾,把整個目錄址記下來 C:\Program Files\Java\jre6\bin
JAVA安裝
• 在前一張我們不是有先找出Path目錄欄,接下來我們把JAVA路徑輸入 進去,在變數值裡的最前端加上 “C:\Program Files\Java\jre6\bin;”(冒號不用打) 這樣就完成與JAVA的連結
JAVA安裝
• 測試JAVA是否正常運作 在開始搜尋→打上cmd→出現命令提示字元→在打上 java -version (如下圖) 有出現版本訊息就代表成功安裝!
eclipse
• 首先在桌面資料夾裡,找 eclipse-SDK-3.7.1-win32 解壓縮到C槽目錄下
eclipse
• 完成後可以看到如下圖
Android SDK安裝
• 打開eclipse,在上面點選 Help → Install New Software … ,
Android SDK安裝
• 點選Add 會出現右下那一欄
Android SDK安裝
• Name 打上 ADT,接著在按Archive…
← 點選桌面 Android資料 夾裡的ADT
Android SDK安裝
• 接著會出現選項,請全部打勾,在一直按Next即可
Android SDK安裝
• 跑完後會出現,直接按下一步即可
Android SDK安裝 • 點我同意,在按Finish
Android SDK安裝 跑安裝
途中會出現以下畫面,直接不理
Android SDK安裝
• 選擇放在eclipse裡的android SDK
點擊這裡
Android SDK安裝
• 選擇你要模擬的版本,勾選完後按 Install
Android SDK安裝
下載完後,點擊模擬器
Android SDK安裝
• 在右手邊新增New…
Android SDK安裝
• Name:test • Target:(選擇你要模擬的版本)
選完後,點Create AVD
Android SDK安裝
• 按start運行接著在按Launch,第一次運行都會等很久 所以 請耐心等候
按下去!
Android SDK安裝
• 這邊要等非常久…
Android SDK安裝
• 看到以下畫面,代表你成功了!
Android SDK安裝
• 接著當你程式寫好,按下RUN執行看結果↓
第零章
Hello, World !
第一個Hello World
• 開啟eclipse,點 File → New → Project…
第一個Hello World
• 點選Android Project
第一個Hello World
• 給予專案名子world,並按下一步
第一個Hello World
• 選擇Android SDK開發版本
第一個Hello World
• 在Package Name裡輸入 world.com • Minimum SDK 選擇 13 (Android 3.2)或是其它版本,接著點選Finish
第一個Hello World
• 完成後在左手邊點src → world.com → WorldActivity.java (點兩下打開)
第一個Hello World
• 建立新的模擬器
第一個Hello World
• 右邊點New…
第一個Hello World
• 取名為 test,在Target選單裡點選Android 3.2 – API Level 13 完成後按下,Create AVD
第一個Hello World
• 按RUN 執行,選擇第一個
第一個Hello World
• 出現 Hello World !
GPS函數類別功能
• Android定義了一個名為com.google.android.maps 的包,其中包含了一系列用於在Google Map上顯 示、控制和堆疊資訊的功能類別,以下有幾個重 要類別介紹。
GPS函數類別功能
• Google Map API – MapActivity:用來顯示Google Map的Activity 類別,他需要連接底層網際網路。
GPS函數類別功能
MapView:顯示地圖View元件,他必須和 MapActivity配合使用
GPS函數類別功能
• MapController:用於控制地圖的移動
GPS函數類別功能
Overlay:顯示在地圖上的可繪製物件
GPS函數類別功能
另外Overlay還有兩種常見的函數: – MylocationOverlay: – 整合了android.location 中接收目前座標的介面。 只需要enableMyLocation()、enableCompass就可 以讓我們的城市擁有即時的MyLocation以及 Compass(指南針)功能。
GPS函數類別功能
Overlay常見的函數之一: – ItemlizedOverlay: – 管理一個OverlayItem鏈結串列,用圖片等資源 在地圖上做風格一致的標記。
GPS函數類別功能
GeoPoint:經緯度位置的物件,用於管理經緯度 座標值,在後面是很重要的函數。
GPS函數類別功能
• Android Location API – LocationManager:本類別提供存取定位服 務的 功能,也提供獲得最佳定位提供者的 功能。
GPS函數類別功能
• Android Location API – LocationProvider:該類別是定位提供者的 抽象 類別。定位提供者具備週期性報告裝 置地 理位置的功能。
GPS函數類別功能
LocationListener:提供定位資訊發生改變 時的 回檔功能。必須事先在定位管理器中 註冊監聽 器物件
GPS函數類別功能
Criteria:該類別使得應用能夠透過 LocationProvider中設定的屬性來選擇合適 的定 位提供者。
第三章
誕生第一支GPS
Google MAP 實作 • 在本例中將教導各位基礎指導,讓各位瞭解 基本的GPS函數使用,我們將分幾項程式介紹 – – – – – – –
誕生第一支GPS程式 控制地圖 地址定位查詢 Android監控GPS位置變化 自我彩繪Google MAP GPS 行動記錄器 萬能 King of GPS
Google MAP API
• 在使用MAP之前我們必須先申請 請照以下步驟:
API KEY ,
– 打開eclipse 有執行過任何程式(例:Holle world) – 在windows介面下,開啟DOS模式(開始→程式 集→所有應用程式→命令提示字元)
Google MAP API
• 打上 keytool -list -alias androiddebugkey -keystore "SDK的debug.keystore 路徑" -storepass android (冒號不用打) • 例如:假設我的路徑是 C:\Users\wuda\.android\debug.keystore • 就在DOS打上 keytool -list -alias androiddebugkey -keystore “C:\Users\wuda\.android\debug.keystore” -storepass android (冒號不用打)如下圖 你的電腦 專屬 指紋 碼
• 在JDK 7.0 使用C:\Program Files (x86)\Java\jdk1.7.0\bin\keytool.exe 產生MD5 憑證指紋,去卻出現SHA1
• 無法使用SHA1 至Android Maps API Key Signup 申請Android Maps API Key 解決方式,在指令中加入-v 的參數 > keytool –list -v keystore debug.keystore如圖:
Google MAP API
• 打開IE,網址列貼上 http://code.google.com/intl/zh-TW/android/mapsapi-signup.html
貼上你的指紋 碼! (記得打勾)
Google MAP API
• 你的電腦專屬KEY,請切記一定要記下來,後面開發GPS都必須要用到!
Google MAP API 往後有用到 Google MAP API ,可以在 /res/layout/main.xml 程式裡貼上KEY 如圖下
誕生第一支GPS
• 建立一個新專案,名為mygoogle
誕生第一支GPS
• 選擇模擬器版本(請選擇後面有 Google APIs )
誕生第一支GPS
• 在 Package Name 打上 map.com Package Name: 這邊建議往後開發程 式時,最好都使用 “專案名+.com” Minimum SDK: 請選擇你上一步所選 擇的SDK
誕生第一支GPS
• • • • • • •
打開main.xml,在中間加上 (記得更換您電腦的API KEY) <com.google.android.maps.MapView android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent“ android:clickable="true" android:apiKey=“輸入您的API KEY”/>
可參考下張圖
誕生第一支GPS
誕生第一支GPS
• 打開 AndroidManifest.xml – 在程式碼中 在 application 底下加入 – <uses-library android:name="com.google.android.maps" />
誕生第一支GPS
• 接著在 manifest 底下加入 – <uses-permission android:name="android.permission.INTERNET"/>
誕生第一支GPS
• 主程式 MygoogleActivity.java – 我們要告訴程式,導入要使用的MAP函數 – import com.google.android.maps.MapActivity; – import com.google.android.maps.MapView;
誕生第一支GPS • 要修改的地方
原本 Activity 改成 MapActivity
加入 要宣告的函數 MapView map;
連結 main.xml 裡的 mapview
最後加入 Override 作結束
誕生第一支GPS
• 完整的主程式參考
誕生第一支GPS
• 完成後按下RUN去執行看看成果!
誕生第一支GPS
• 有出現以下圖,代表您成功了!
誕生第一支GPS
• 要是您手邊有任何Android的設備,也是可以當場RUN看看喔! •
假設手邊有一台ASUS 的變形平板電腦,那麼可以先去ASUS官方網站下載ASUS Sync 同 步軟體 驅動程式。
誕生第一支GPS
• 安裝完成後,開啟連線功能。
誕生第一支GPS
• 要是您手上有 Samsung 設備,請到官方下載 Kies
誕生第一支GPS
• 安裝完成後,與電腦做同步化。
誕生第一支GPS
• 回到eclipse在執行一次RUN,這次選擇設備上執行。
誕生第一支GPS
• 在平板電腦上成功執行的畫面!
第四章
實習程式
GPS實戰演練
• 先將要使用到的Google Map類別叫出 – – – – –
import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import android.os.Bundle;
GPS實戰演練
• public class GoogleMap1Activity extends MapActivity { • private MapView map; //宣告 google map 物件 • private MapController mapController; //宣告 google map 控制物件 • @Override • public void onCreate(Bundle savedInstanceState) { • super.onCreate(savedInstanceState); • setContentView(R.layout.main);
GPS實戰演練
• • • • • • • • • • • • • • •
map = (MapView) findViewById(R.id.map) ; //取得 google map 元件 mapController = map.getController(); mapController.setZoom(17); //設定放大倍率1(地球)-21(街景) //設定地圖初始座標值:緯度,經度 GeoPoint SunMoonLake = new GeoPoint( (int) (23.862696 * 1000000),(int) (120.904211 * 1000000)); mapController.animateTo(SunMoonLake); //中心點--日月潭 } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } }
GPS實戰演練
GPS實戰演練
• 在上圖我們可以看到,一開始設定的初始位置 • GeoPoint SunMoonLake = new GeoPoint((int) (23.862696 * 1000000),(int) (120.904211 * 1000000)); • mapController.animateTo(SunMoonLake); //中心點--日月潭 • } • 顯示在日月潭上,有顯示出來就代表成功了,是不是很簡單呢!
GPS實戰演練
控制地圖
GPS實戰演練
• 在上一個單元裡建立的Google 地圖應用程式無法 控制放大縮小,也無法拖曳移動顯示其他地方, 這次我們增加一些函數,以控制我們需要的功能。
GPS實戰演練
• 這次我們只要把前一單元程式碼增加控制元件就可以了 • 主程式,尋找 • map = (MapView) findViewById(R.id.map) ; //取得 google map 元件 • map.setBuiltInZoomControls(true); //增加這一行,地圖縮放和拖 曳內建功能 • • mapController = map.getController(); • mapController.setZoom(17); //設定放大倍率1(地球)-21(街景)
GPS實戰演練
• • • • • •
再到 layout → main.xml 裡找到 <com.google.android.maps.MapView android:id="@+id/map" android:layout_height="fill_parent" android:layout_width="fill_parent" android:clickable=“true“ <!– 增加這一行,控制地圖 --> android:apiKey=“Google API Key" />
• 完成後下一張可以看到控制鈕↓
GPS實戰演練
GPS實戰演練
地址定位查詢
GPS實戰演練
• 在本單元裡,要是我們迷路或是想找地點,我們是否可以增加 查詢的 功能呢? 當然可以! 請往下看 • 本單元分二部分 – 座標定位查詢 – 文字定位查詢
GPS實戰演練
• • • • • • • • • •
(一)座標定位查詢 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); …. //設定地圖初始座標值:緯度,經度 GeoPoint gp = new GeoPoint( (int) (23.862696 * 1000000),(int) (120.904211 * 1000000)); mapController.animateTo(gp); }
GPS實戰演練
• 再來我們要新增搜尋程式 • private Button.OnClickListener myListener=new Button.OnClickListener(){ • public void onClick(View v){ • double lon=Double.parseDouble(edtLon.getText().toString()); • double lat=Double.parseDouble(edtLat.getText().toString()); • GeoPoint gp = new GeoPoint( • (int) (lat * 1000000),(int) (lon * 1000000)); • mapController.animateTo(gp); //中心點 • } • };
GPS實戰演練
這是初始座標 地圖:日月潭
GPS實戰演練
輸入經緯度座標 後,我們可以看 到台中公園
GPS實戰演練
• (二)文字定位查詢 – Geocoder介紹 • Geocoder 的主要用途為轉換街道地址,將其對應至地理座 標。最好符合以下地理編碼要求格式,以提升查詢的成功 率: (下圖)
GPS實戰演練
遵循相關國家/地區郵政服務所使用的格式指定地址。 不要指定額外的地址項目,例如相關國家/地區郵政服務未納入 地址定義的公司名稱、單位號碼、樓層號碼或套房號碼。
如果可能的話,優先使用建築物的街道號碼,而非建築物名稱。 如果可能的話,優先使用包含街道號碼的地址,而非相交街道。 不要提供「建議」,例如附近地標。
GPS實戰演練
• • • • • •
新增2個函數類別 import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import com.google.android.maps.MapController; import com.google.android.maps.GeoPoint; import android.location.Address; – //取得要查詢的文字
• import android.location.Geocoder; – //轉換街道地址,將其對應至地理座標
GPS實戰演練
• strings.xml – – – – – –
<string name="default_address">台北火車站</string> <string name="Lat">緯度</string> <string name="Lon">經度</string> <string name="Find">查詢</string> <string name="NotFind">查無相關地址資訊</string> <string name="Ads">地址</string>
GPS實戰演練
• 主程式 – – – – – – – – – –
tv_Lat = (TextView)this.findViewById(R.id.tv_Lat); tv_Lon = (TextView)this.findViewById(R.id.tv_Lon); tv_Address = (TextView)this.findViewById(R.id.tv_Address); tv_Address.setText(this.getResources().getText(R.string.Ads)); et_Address = (EditText)this.findViewById(R.id.et_Address); btn_Find = (Button)this.findViewById(R.id.btn_Find); btn_Find.setText(this.getResources().getText(R.string.Find)); String strDefAddress = this.getResources().getText(R.string.default_address).toString(); et_Address.setText(strDefAddress); //將strings.xml裡的default_address欄位的值取出來轉換成字串
GPS實戰演練
• 將查詢到的座標經緯度顯示出來 – private GeoPoint getGeoPointByAddress(String strAddress){ – GeoPoint mGPoint = null; – try{ – /*建立Geocoder物件*/ – Geocoder mGcoder = new Geocoder(FindAddressMap.this , Locale.getDefault()); – /*取得一個地址集合*/ – List<Address> lsAddress = mGcoder.getFromLocationName(strAddress , 1); – if(!lsAddress.isEmpty()){ – Address mLocation = lsAddress.get(0); – /*將Address轉換成GeoPoint*/ – mGPoint = new GeoPoint((int)(mLocation.getLatitude() * 1E6) , – (int)(mLocation.getLongitude() * 1E6));
GPS實戰演練
• • • • • • • • • • • • • • •
tv_Lat.setText( this.getResources().getText(R.string.Lat) + Double.toString(mLocation.getLatitude())); tv_Lon.setText( this.getResources().getText(R.string.Lon) + Double.toString(mLocation.getLongitude())); } else{ tv_Lat.setText(this.getResources().getText(R.string.NotFind)); tv_Lon.setText(this.getResources().getText(R.string.NotFind)); } }catch(Exception e){ e.printStackTrace(); } return mGPoint; }
GPS實戰演練
• 完成後的初始點
GPS實戰演練
• 在上方輸入查詢結果
GPS實戰演練
使MAP 加上地圖控制功能
GPS實戰演練
• 本節裡將教導各位去做地圖的控制 – 一般地圖與衛星地圖 – 預設選單
GPS實戰演練
• 先加入要使用的套件函數 • • • • • • •
import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem;
GPS實戰演練 • public class GoogleMap2Activity extends MapActivity { • private MapView map; // 宣告 google map 物件 • private MapController mapController; // 宣告 google map 控制物件 • @Override • public void onCreate(Bundle savedInstanceState) { • super.onCreate(savedInstanceState); • setContentView(R.layout.main);
GPS實戰演練 • map = (MapView) findViewById(R.id.map) ; //取得 google map 元件 • map.setBuiltInZoomControls(true); //地圖縮放和拖曳 • map.setTraffic(false); //設定地圖檢示模式:一般地圖 • map.setSatellite(true); //衛星地圖 • • mapController = map.getController(); • mapController.setZoom(17); //設定放大倍率1(地球)21(街景) • mapController.animateTo(Taipei101); //中央點為 台北 101
GPS實戰演練 • • • • • • • • • • • • • •
設定5個選單,分別對應位置 protected static final int MENU_Traffic =Menu.FIRST ; protected static final int MENU_Satellite =Menu.FIRST +1; protected static final int MENU_Taipei101 = Menu.FIRST+2; protected static final int MENU_SunMoonLake = Menu.FIRST+3; protected static final int MENU_Kaushong = Menu.FIRST+4; // set menu public boolean onCreateOptionsMenu(Menu menu){ menu.add(0,MENU_Traffic,0,"一般地圖"); menu.add(0,MENU_Satellite,1,"衛星地圖"); menu.add(0,MENU_Taipei101, 2,"台北 101"); menu.add(0,MENU_SunMoonLake, 3,"日月潭"); menu.add(0,MENU_Kaushong, 4,"高雄夜市"); return true;
GPS實戰演練 • //設定地圖座標值:緯度,經度 • GeoPoint Taipei101 = new GeoPoint( • (int) (25.033194 * 1000000),(int) (121.564837 * 1000000)); • GeoPoint SunMoonLake = new GeoPoint( • (int) (23.862696 * 1000000),(int) (120.904211 * 1000000)); • GeoPoint Kaushong = new GeoPoint( • (int) (22.633428 * 1000000),(int) (120.302368 * 1000000));
GPS實戰演練 • • • • • • • • • • • • • • • • •
public boolean onOptionsItemSelected(MenuItem item){ switch (item.getItemId()){ case MENU_Traffic: map.setSatellite(false); //一般地圖 break; case MENU_Satellite: map.setSatellite(true); //衛星地圖 break; case MENU_Taipei101: //台北 101 mapController.animateTo(Taipei101); break; case MENU_SunMoonLake: //日月潭 mapController.animateTo(SunMoonLake); break; case MENU_Kaushong: //高雄六合夜市 mapController.animateTo(Kaushong); break;
GPS實戰演練
• 完成後的樣子
GPS實戰演練
在MAP上標上圖案
GPS實戰演練
• 在現有的MAP上,標上你所喜愛的圖案
GPS實戰演練 • • • • • • • • • • • • • •
先導入要使用的函數 import java.util.ArrayList; import java.util.List; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; . … …. import com.google.android.maps.Overlay; import com.google.android.maps.OverlayItem;
GPS實戰演練 • • • • • •
可以先在選單裡,設定好你要的地點 public class GPS3Activity extends MapActivity { private String[] locTitle = {"台北市:","南投縣:","高雄市:"}; private String[] locSnippet = {"台北 101","日月潭","六合夜市"}; private Double[][] locPoint = { {25.033194,121.564837},{23.862696,120.904211},{22.633428,120.302368 }};
• private MapView map; • private MapController mapController; • private MyLocationOverlay LocationOverlay; • private LandMarkOverlay myMarkOverlay; • int[] resIds = new int[]{ R.drawable.onebit_01, R.drawable.onebit_02,R.drawable.onebit_03};
GPS實戰演練 • • • • • • • • • • • • • • • •
map = (MapView) findViewById(R.id.map) ; //取得 google map 元件 map.setBuiltInZoomControls(true); // 地圖縮放和拖曳 map.setSatellite(true); // 衛星地圖 mapController = map.getController(); mapController.setZoom(17); //設定放大倍率
List<Overlay> overlays = map.getOverlays(); // 建立圖層的 List 清單 LocationOverlay = new MyLocationOverlay(this, map); LocationOverlay.runOnFirstFix(new Runnable() { public void run(){ mapController.animateTo(LocationOverlay.getMyLocation()); } }); overlays.add(LocationOverlay); // 將定位圖層加入圖層清單中
GPS實戰演練 • • • • • • • • • • • • • •
// 建立地標圖層 並標示圖示 Drawable icon=getResources().getDrawable(resIds[0]); icon.setAlpha(120);// 透明度(0~255) icon.setBounds(0, 0, icon.getMinimumWidth(), icon.getMinimumHeight()); myMarkOverlay = new LandMarkOverlay(icon); // 加入地標物件 for (int i=0;i<3;i++){ double dLat = locPoint[i][0];// 緯度 double dLon = locPoint[i][1];;// 經度 GeoPoint gp = new GeoPoint((int)(dLat * 1e6), (int)(dLon * 1e6)); OverlayItem overlayitem = new OverlayItem(gp, locTitle[i], locSnippet[i]); myMarkOverlay.addMyOverlayItem(overlayitem); // 地標物件加入 位置、標題、 說明文字 } overlays.add(myMarkOverlay); // 將地標圖層加入圖層清單中
GPS實戰演練 • • • • • • • • • • • • •
protected static final int MENU_Traffic =Menu.FIRST ; protected static final int MENU_Satellite =Menu.FIRST +1; protected static final int MENU_Taipei101 = Menu.FIRST+2; protected static final int MENU_SunMoonLake = Menu.FIRST+3; protected static final int MENU_Kaushong = Menu.FIRST+4; // 建立功能表 public boolean onCreateOptionsMenu(Menu menu){ menu.add(0,MENU_Traffic,0,"一般地圖"); menu.add(0,MENU_Satellite,1,"衛星地圖"); menu.add(0,MENU_Taipei101, 2,"台北 101"); menu.add(0,MENU_SunMoonLake, 3,"日月潭"); menu.add(0,MENU_Kaushong, 4,"高雄夜市"); return true;
GPS實戰演練
• /設定地圖座標值:緯度,經度 • GeoPoint Taipei101 = new GeoPoint( • (int) (25.033194 * 1000000),(int) (121.564837 * 1000000)); • GeoPoint SunMoonLake = new GeoPoint( • (int) (23.862696 * 1000000),(int) (120.904211 * 1000000)); • GeoPoint Kaushong = new GeoPoint( • (int) (22.633428 * 1000000),(int) (120.302368 * 1000000));
GPS實戰演練 • • • • • • • • • • • • • • • • •
public boolean onOptionsItemSelected(MenuItem item){ switch (item.getItemId()){ case MENU_Traffic: map.setSatellite(false); // 一般地圖 break; case MENU_Satellite: map.setSatellite(true); // 衛星地圖 break; case MENU_Taipei101: //台北 101 mapController.animateTo(Taipei101); break; case MENU_SunMoonLake: //日月潭 mapController.animateTo(SunMoonLake); break; case MENU_Kaushong: //高雄六合夜市 mapController.animateTo(Kaushong); break;
GPS實戰演練 • private class LandMarkOverlay extends ItemizedOverlay<OverlayItem> { • private ArrayList<OverlayItem> myOverlayItems=new ArrayList<OverlayItem>(); • public LandMarkOverlay(Drawable icon) { • super(icon); • }
• •
@Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { • super.draw(canvas, mapView, false);
GPS實戰演練 • • • • • • • • • • • • • • • • •
public void addMyOverlayItem(OverlayItem overlayItem) { myOverlayItems.add(overlayItem); populate(); } @Override protected OverlayItem createItem(int i) { return myOverlayItems.get(i); } @Override public int size() { return myOverlayItems.size(); } @Override protected boolean onTap(int pIndex) { Toast.makeText(GPS3Activity.this, myOverlayItems.get(pIndex).getTitle()+ myOverlayItems.get(pIndex).getSnippet(), Toast.LENGTH_SHORT).show();
GPS實戰演練
• 實機運作
GPS實戰演練
使用GPS取得現在位置
GPS實戰演練
• 若要取得目前所在位置,則必須加入定位的功能,才能找 到自己所在位置 • Android提供設備定位的方法有 – GPS定位 (最精準,但有時會礙於天氣) – 網路定位 (無線定位最差,但室內有線則最準確)
• 接下來用範例 做教學
GPS實戰演練
• 套入我們需要用到的套件包 • • • • • • • • • • •
import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import android.app.Activity; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.Toast; //顯示在畫面上的提示VIEW
GPS實戰演練 設定功能 • • • • • • • • • • • • • • •
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); map = (MapView) findViewById(R.id.map) ; //取得 google map 元件 map.setBuiltInZoomControls(true); // 地圖縮放和拖曳 map.setSatellite(true); // 設定地圖檢示模式:衛星地圖 mapController = map.getController(); mapController.setZoom(17); //設定放大倍率1(地球)-21(街景) locMgr = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); bestProv = locMgr.getBestProvider(criteria, true); }
GPS實戰演練 將取得的座標轉換為公版座標 • public void onLocationChanged(Location location) { • GeoPoint gp=new GeoPoint( • (int) (location.getLatitude() * 1000000), //經緯度各 乘上1000000 • (int) (location.getLongitude() * 1000000) ); • mapController.animateTo(gp); // 指定地圖現在位置 • String x="緯=" + Double.toString(location.getLatitude()); • String y="經=" + Double.toString(location.getLongitude()); • Toast.makeText(GPS1Activity.this,x + "\n\r" + y, Toast.LENGTH_LONG).show(); • }
GPS實戰演練 • public void onLocationChanged(Location location) • 是手機定位地點改變執行的方法,傳入的參數 location 可以取得目前定位點 • public void onProviderDisabled(String provider) • 用來處理當GPS或網路定位功能關閉時會以 LocationManager的removeUpdates()方法來停止
GPS實戰演練
• public void onProviderEnabled(String provider) • 用來處理當GPS或網路定位開啟時,會以 LocationManager物件的 requestLocationUpdates()啟動定位 • public void onStatusChanged(String provider, int status, Bundle extras) • 用來處理定位狀態改變時,重新取得一個 最佳的定位方式
GPS實戰演練
Android監控GPS位置變化
GPS實戰演練
• 要是在市區迷路,卻想知道自己所在位置,好讓自己離開迷路噩夢? • 在本單元將教導各位如何讓GPS 自己定位自己的位置,並隨時監控著!
GPS實戰演練
• AndroidManifest.xml • <uses-sdk android:minSdkVersion=“13” /> (此處更改版本) • <uses-permission android:name="android.permission.INTERNET"></usespermission> • <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></usespermission> • <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></usespermission>
GPS實戰演練 • • • • • • • • • • • •
main.xml <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Zoom (+)" android:id="@+id/btn_ZoomOut"> </Button> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Zoom (-)" android:id="@+id/btn_ZoomIn"> </Button>
• • • • • • • •
</LinearLayout> <com.google.android.maps.MapView android:id="@+id/MapView01" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true" android:apiKey=“此處加入API KEY"
GPS實戰演練
• • • • • • • • • • •
Strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, LocationLinsterMap!</string> <string name="app_name">LocationLinsterMap</string> <string name="Str_Lat">緯度</string> <string name="Str_Long">經度</string> <string name="Btn_Listener">啟動地點監聽</string> <string name="Btn_ZoomOut">放大</string> <string name="Btn_ZoomIn">縮小</string> </resources>
GPS實戰演練 • /*註冊地點更新*/ • btn_Listener.setOnClickListener(new View.OnClickListener() { • @Override • public void onClick(View v) { • • • • • •
/*建立篩選規則*/ Criteria mCriteria = new Criteria(); mCriteria.setAccuracy(Criteria.ACCURACY_FINE); mCriteria.setAltitudeRequired(false); mCriteria.setBearingRequired(false); mCriteria.setCostAllowed(true);
• mCriteria.setPowerRequirement(Criteria.POWER_LOW); • /*取得最適合的提供者*/ • String mBestProvider = mLocManager.getBestProvider(mCriteria, true); • /*取得一開始的地點資訊*/ • Location mFirstLoc = mLocManager.getLastKnownLocation(mBestProvider); • if(mFirstLoc != null){ • ReloadMap(mFirstLoc); • } • /*註冊地點更新監聽*/ • mLocManager.requestLocationUpdates(mBestProvider , 1000 , 0 , LocListener
GPS實戰演練 • • • • • • • • • • • • • •
/*放大顯示地區*/ btn_ZoomOut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mZoomLevel++; if(mZoomLevel > mMapView.getMaxZoomLevel()){ mZoomLevel = mMapView.getMaxZoomLevel(); } mMapController.setZoom(mZoomLevel); } }); /*縮小顯示地區*/ btn_ZoomIn.setOnClickListener(new View.OnClickListener() {
• •
@Override public void onClick(View v) {
• • • • • •
mZoomLevel--; if(mZoomLevel < 1 ){ mZoomLevel =1; } mMapController.setZoom(mZoomLevel); }
GPS實戰演練
• • • • • • • • • • •
private void ReloadMap(Location location){ java.text.DecimalFormat df = new java.text.DecimalFormat("##0.00000"); /*設定顯示訊息*/ String mStrInfo = String.format("%s = %s , %s %s", this.getResources().getString(R.string.Str_Lat), df.format(location.getLatitude()), this.getResources().getString(R.string.Str_Long), df.format(location.getLongitude())); tv_View01.setText(mStrInfo); GeoPoint mPoint = new GeoPoint( (int)(location.getLatitude() * 1E6) , (int)(location.getLongitude() * 1E6)); mMapController.setCenter(mPoint); mMapView.displayZoomControls(true); mMapController.setZoom(mZoomLevel); }
GPS實戰演練
GPS行動記錄器
GPS實戰演練 • 在GPS精準下,可用在路徑紀錄,以方便往後想知道自己是否走過這 條路,或是分享給其他人 • 主程式共分2個 – MyOverlay.java – PathRecordMap.java
GPS實戰演練 • 首先先看 MyOverlay.java
• • • • • • • • • • •
先導入需要用到的 套件 import android.widget.TextView; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.RectF; import com.google.android.maps.GeoPoint;//座標資訊 import com.google.android.maps.MapView;//顯示MAP import com.google.android.maps.Overlay; import com.google.android.maps.Projection; import android.content.res.Resources;
GPS實戰演練 • • • • • • • • • • •
宣告類別函數 public class MyOverlay extends Overlay{ static int START_TYPE = 1; static int STOP_TYPE = 2; static int PATH_TYPE = 3; //宣告動作層級 GeoPoint mLastPoint, mCurPoint; TextView mTextView; int mRad = 10; int mDrawType; Resources mRes;
GPS實戰演練 •
public void draw(Canvas canvas, MapView mapView, boolean shadow){
• • •
Paint mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setFakeBoldText(false);
• • • • • • • • • • •
if(mDrawType == MyOverlay.START_TYPE ){ Projection mProjection = mapView.getProjection(); Point mPoint = new Point(); /*取得像素位置*/ mProjection.toPixels(mCurPoint, mPoint); mPaint.setARGB(250, 255 , 0, 0); RectF mRect = new RectF(mPoint.x - mRad, mPoint.y - mRad , mPoint.x + mRad , mPoint.y + mRad); canvas.drawRect(mRect, mPaint); /*繪製文字*/ canvas.drawText(mRes.getString(R.string.Str_StartPos), mPoint.x - mRad , mPoint.y mRad ,mPaint); }
•
GPS實戰演練 • • • • • • • •
這邊在做取得的像素繪製在地圖上 else if(mDrawType == MyOverlay.STOP_TYPE){ Projection mProjection = mapView.getProjection(); Point mPoint1 = new Point(); Point mPoint2 = new Point(); /*取得像素位置*/ mProjection.toPixels(mLastPoint, mPoint1); mProjection.toPixels(mCurPoint, mPoint2);
GPS實戰演練 • • • • • • • • • • •
mPaint.setARGB(255, 0, 114, 227); /*先將剩餘路線畫路線*/ canvas.drawLine(mPoint1.x, mPoint1.y, mPoint2.x, mPoint2.y, mPaint); /*設定橢圓的矩形範圍*/ RectF mOval = new RectF(mPoint2.x - mRad, mPoint2.y - mRad , mPoint2.x + mRad , mPoint2.y + mRad);
mPaint.setARGB(255, 0, 0, 255); /*繪製橢圓*/ canvas.drawOval(mOval, mPaint); /*繪製文字*/ canvas.drawText(mRes.getString(R.string.Str_StopPos), mPoint2.x - mRad , mPoint2.y - mRad ,mPaint); • }
GPS實戰演練 • • • • • • • • • • •
else if(mDrawType == MyOverlay.PATH_TYPE){ Projection mProjection = mapView.getProjection(); Point mPoint1 = new Point(); Point mPoint2 = new Point(); /*取得像素位置*/ mProjection.toPixels(mLastPoint, mPoint1); mProjection.toPixels(mCurPoint, mPoint2); mPaint.setARGB(255, 0, 114, 227); /*畫路線*/ canvas.drawLine(mPoint1.x, mPoint1.y, mPoint2.x, mPoint2.y, mPaint); }
GPS實戰演練 •
接著看 PathRecordMap.java
• • • • • • •
import java.text.*; import java.util.List; import android.os.Bundle; import android.view.View; import android.widget.*; import android.location.*; import com.google.android.maps.*;
• 在這裡是將 MAP 顯示出來,並做結合
GPS實戰演練
• • • • • • • • • • • •
先宣告 public class PathRecordMap extends MapActivity { TextView tv_Info; Button btn_Start; Button btn_Stop; MapView mMapView; MapController mMapController; LocationManager mLocManager; String mBestProvider; GeoPoint mFirstPoint , mSecondPoint; int mZoomLevel = 20; double mTotalDistance;
GPS實戰演練 • • • • • • • • • • • • • • •
將對應到String裡的字串做宣告 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv_Info = (TextView)this.findViewById(R.id.tv_Infor); btn_Start = (Button)this.findViewById(R.id.btn_Start); btn_Stop = (Button)this.findViewById(R.id.btn_Stop); btn_Start.setText(this.getResources().getString(R.string.btn_Start)); btn_Stop.setText(this.getResources().getString(R.string.btn_Stop)); mLocManager = (LocationManager) this.getSystemService(LOCATION_SERVICE); mMapView = (MapView)this.findViewById(R.id.MapView01); mMapController = mMapView.getController(); mMapController.setZoom(mZoomLevel);
GPS實戰演練
• • • • • • • • • • •
/*建立篩選規則*/ Criteria mCriteria = new Criteria(); mCriteria.setAccuracy(Criteria.ACCURACY_FINE); mCriteria.setAltitudeRequired(false); mCriteria.setBearingRequired(false); mCriteria.setCostAllowed(true); mCriteria.setPowerRequirement(Criteria.POWER_LOW); /*取得最適合的提供者*/ mBestProvider = mLocManager.getBestProvider(mCriteria, true);
btn_Start.setOnClickListener(new View.OnClickListener() {
GPS實戰演練 • public void onClick(View v) {
• /*清空目前已加入的Overlay*/ • List<Overlay> mList = mMapView.getOverlays(); • mList.clear(); • /*取得一開始的地點資訊*/ • Location mStarttLoc = mLocManager.getLastKnownLocation(mBestProvider); • if(mStarttLoc != null){ • mFirstPoint = new GeoPoint((int)(mStarttLoc.getLatitude() * 1E6),(int)(mStarttLoc.getLongitude() * 1E6)); • /*加入起始點*/
• MyOverlay mStartOverlay = new MyOverlay(null,mFirstPoint, MyOverlay.START_TYPE, PathRecordMap.this.getResources()); • mList.add(mStartOverlay); • ReloadMap(mStarttLoc); • /*將計算距離設成0*/ • mTotalDistance = 0; • } • /*註冊地點更新監聽*/ • mLocManager.requestLocationUpdates(mBestProvider , 3000 , 10 , LocListener); • btn_Start.setEnabled(false); • btn_Stop.setEnabled(true); • tv_Info.setText("");
GPS實戰演練 •
btn_Stop.setOnClickListener(new View.OnClickListener() {
• public void onClick(View v) { • Location mEndLoc = mLocManager.getLastKnownLocation(mBestProvider); • if(mEndLoc != null){ • /*位置改變,紀錄上一個位置,mSecondPoint == null 表示位置沒有被 更新過*/ • if(mSecondPoint != null){ • mFirstPoint = mSecondPoint; • } • mSecondPoint = new GeoPoint((int)(mEndLoc.getLatitude() * 1E6),(int)(mEndLoc.getLongitude() * 1E6));
• /*加入起始點*/ • MyOverlay mStopOverlay = new MyOverlay(mFirstPoint, mSecondPoint, MyOverlay.STOP_TYPE, PathRecordMap.this.getResources()); • mMapView.getOverlays().add(mStopOverlay); • ReloadMap(mEndLoc); • mTotalDistance += GetDistance( • mFirstPoint.getLatitudeE6()/1E6, • mFirstPoint.getLongitudeE6()/1E6, • mSecondPoint.getLatitudeE6()/1E6, • mSecondPoint.getLongitudeE6()/1E6
GPS實戰演練 • • • • • • • • •
/*格式化距離*/ NumberFormat mFormatter = new DecimalFormat("###.##"); String mStrInfo = String.format(PathRecordMap.this.getResources().getString(R.string.Str_Dist ance), mFormatter.format(mTotalDistance)); tv_Info.setText(mStrInfo); /*解除參考*/ mFirstPoint = null; mSecondPoint = null; } mLocManager.removeUpdates(LocListener);
• • •
btn_Start.setEnabled(true); btn_Stop.setEnabled(false); }
GPS實戰演練 • /*初始化LocationListener物件*/ • private final LocationListener LocListener = new LocationListener(){ • • /*當手機地點改變時,系統將會呼叫此方法*/ • public void onLocationChanged (Location location){ • if(location != null){ • /*位置改變,紀錄上一個位置,mSecondPoint == null 表示是第一次位 置更新*/ • if(mSecondPoint != null){ • mFirstPoint = mSecondPoint; • }
• /*將最新位置指派給 mSecondPoint 變數*/ • mSecondPoint = new GeoPoint((int)(location.getLatitude() * 1E6),(int)(location.getLongitude() * 1E6)); • /*建立畫線的 Overlay*/ • MyOverlay mStopOverlay = new MyOverlay(mFirstPoint, mSecondPoint, MyOverlay.PATH_TYPE, PathRecordMap.this.getResources()); • mMapView.getOverlays().add(mStopOverlay); • ReloadMap(location); • mTotalDistance += GetDistance( • mFirstPoint.getLatitudeE6()/1E6, • mFirstPoint.getLongitudeE6()/1E6, • mSecondPoint.getLatitudeE6()/1E6, • mSecondPoint.getLongitudeE6()/1E6 • );
GPS實戰演練
• private void ReloadMap(Location location){ • GeoPoint mPoint = new GeoPoint( (int)(location.getLatitude() * 1E6) , (int)(location.getLongitude() * 1E6)); • mMapController.setCenter(mPoint); • mMapView.displayZoomControls(true); • mMapController.setZoom(mZoomLevel); • } • • @Override • public boolean isRouteDisplayed(){ • return false; • }
GPS實戰演練 • • • • • • • • • • • • •
public double GetDistance(double Lat1, double Long1, double Lat2, double Long2) { double Lat1r = (Math.PI/180) * Lat1; double Lat2r = (Math.PI/180) * Lat2; double Long1r = (Math.PI/180) * Long1; double Long2r = (Math.PI/180) * Long2; double R = 6371; /* 地球半徑 (km) */ double mDistance = Math.acos(Math.sin(Lat1r) * Math.sin(Lat2r) + Math.cos(Lat1r) * Math.cos(Lat2r) * Math.cos(Long2r - Long1r)) * R; return mDistance; }
GPS實戰演練
• 再來看 String.xml 前面有提到的引入字串 • • • • • • • • •
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, PathRecordMap!</string> <string name="app_name">PathRecordMap</string> <string name="btn_Start">啟動紀錄</string> <string name="btn_Stop">停止紀錄</string> <string name="Str_StartPos">起點</string> <string name="Str_StopPos">終點</string> <string name="Str_Distance">全部路程 : %s 公里</string>
• </resources>
• 成功後的圖
教育部智慧生活整合性人才培育計畫
最後看完上述的平台介紹以及程式開發,ANDROID+GPS的 定位服務,其實是可以帶動很多生活裡面,要如何創造生 活結合,就由各位去想像了!
Intelligent living laboratory
168