android google maps

Post on 30-Dec-2015

87 Views

Category:

Documents

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

Android 智慧型手機程式設計. Android Google Maps. 建國科技大學 資管系 饒瑞佶 2012/4 V1 2012/8 V2 2013/5 V3 V4. Google Maps. Reference : https://developers.google.com/maps/documentation/android/start#creating_an_api_project. 取得 Google Map API. Step1: 先進入 JDK 目錄. Google Maps. 透過 keytool.exe 建立認證指紋 SHA1 - PowerPoint PPT Presentation

TRANSCRIPT

Android Google Maps

建國科技大學 資管系饒瑞佶

2012/4 V12012/8 V2

2013/5 V3 V4

Android 智慧型手機程式設計

Google Maps

• 取得 Google Map API

Step1: 先進入 JDK 目錄

Reference :https://developers.google.com/maps/documentation/android/start#creating_an_api_project

Google Maps

• 透過 keytool.exe 建立認證指紋 SHA1• 需要 debug_keystore 路徑

新版 IDE 已經列出 SHA1 碼不過好像不太能用

下一步驟用

重做一次認證

• 輸入• keytool -list -v -keystore "C:\Documents and

Settings\Administrator\.android\debug.keystore“

• 預設密碼是 android

來自 Eclipse 內的 default keystore

Google Maps

• 產生認證指紋

要的是 SHA1 編碼

Google Maps• 進入 Google Map API Key 申請頁面• http://code.google.com/intl/zh-Tw/android/add-ons/google-

apis/maps-api-signup.html ( 不再使用 )

輸入認證指紋碼

目前不用

Google Maps Android API Version 1 開發法已經停用

• http://cheng-min-i-taiwan.blogspot.tw/2013/04/google-maps-android-api-v2-android.html

• 新版 API 需要配合 Google Play Services

進入申請頁面

需要登入 Google

• https://developers.google.com/maps/documentation/javascript/tutorial#api_key

Google Maps

• 進入 Google Map API Key 申請頁面

Reference :這裡有做法https://developers.google.com/maps/documentation/android/start#creating_an_api_project

API Access

使用 SHA1 與 package Name

result

使用 API Key

首先將 API key 加入 AndroidManifest.xml

<meta-data    android:name="com.google.android.maps.v2.API_KEY"    android:value="your_api_key"/>

加入使用權限

加入使用權限到 AndroidManifest.xml

<permission android:name="ctu.rcjao.helloandroid.permission.MAPS_RECEIVE“ android:protectionLevel="signature"/><uses-permission android:name="ctu.rcjao.helloandroid.permission.MAPS_RECEIVE"/>

改成自己的package name

改成自己的package name

加入使用權限到 AndroidManifest.xml

Use permission

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/><!-- The following two permissions are not required to use     Google Maps Android API v2, but are recommended. --><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

再加入 use-feature

uses-feature

<uses-feature        android:glEsVersion="0x00020000"        android:required="true"/>

最後加入地圖

Xml 檔案

<fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.SupportMapFragment"/>

加入下列 code

JAVA 程式

public class Map extends FragmentActivity {

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map);}}

執行

結果不能跑,有錯誤!

打開 SDK 中的 SDK Manager ,找到 Extras 並安裝 Android Support Library 及 Google Play Services 兩個項目

匯入 Google Play Services 函式庫File > Import > Android > Existing Android Code Into Workspace

路徑:android-sdk\extras\google\google_play_services\libproject\google-play-services_lib

匯入完成

專案要加入這個 library

還有要開 google Maps Android API v2

不是這個喔!

執行• 需要實體手機• 過程中可能需要更新 Google Play

Google Maps

實體手機

發佈到 AVD2.2

有了,但是還是不行!換個版本 4.0.3

使用 SDK 4.0.3

AVD 設定

設定模擬器顯示地圖• 首先在模擬器中安裝 Google Play Service• 修改 System 目錄之檔案權限,允許寫入權限

– adb shell mount -o remount,rw -t yaffs2 /dev/block/mtdblock0 /system

– adb shell chmod 777 /system/app• adb push GoogleLoginService.apk /system/app/• adb push GoogleServicesFramework.apk /system/app/• adb push Phonesky.apk /system/app/

• adb install Maps_6.12.0.apk • adb install

com.google.android.gms-3.apk

漫長的等待… .

Google Play Service要夠新

如果出現要 update Google Play Service !

通常是失敗,因為不支援線上更新

下載新的 APK 重裝就可以了

result

在 Google Maps 上加標示• SDK 至少要 4.0@SuppressLint("NewApi")public class Main extends FragmentActivity { // 要顯示的座標 static final LatLng CTU = new LatLng(24.06660656734983, 120.54975986480713); private GoogleMap map;

@SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 取得地圖物件 map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); // 建立紅色氣球標示 Marker mk = map.addMarker(new MarkerOptions().position(CTU).title("建國科技大學 ").snippet("資管系 ")); // 設定縮放大小是 16 ,且將標示點放在正中央 map.moveCamera(CameraUpdateFactory.newLatLngZoom(CTU, 16)); }}

如果更早的 SDK 也要可以用 map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

result

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >

<fragment android:layout_weight="1" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.SupportMapFragment"/> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_weight="0" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 地圖 " /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 衛星 " /> </LinearLayout></LinearLayout>

修改 UI 的 xml

加入這段來切換地圖種類

原地圖設定 layout_weight

result

Button btn_normalview=(Button)findViewById(R.id.button1);Button btn_satellitetview=(Button)findViewById(R.id.button2);btn_normalview.setOnClickListener(new Button.OnClickListener(){ public void onClick(View arg0) { map.setMapType(GoogleMap.MAP_TYPE_NORMAL); // 顯示地圖模式 }}); btn_satellitetview.setOnClickListener(new Button.OnClickListener(){ public void onClick(View arg0) { map.setMapType(GoogleMap.MAP_TYPE_SATELLITE); // 顯示衛星模式 } });

Oncreate 中加入下列 code

地址轉座標功能將下列 code 加入 UI (fragment 前 )

<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_weight="0" > <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" > <requestFocus /> </EditText> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 顯示 " /> <TextView android:id="@+id/textview1" android:text="" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>

地址轉座標功能Button btn_address_to_geo=(Button)findViewById(R.id.button3);btn_address_to_geo.setOnClickListener(new Button.OnClickListener(){ public void onClick(View arg0) { try { EditText inputaddress=(EditText)findViewById(R.id.editText1); tv1=(TextView)findViewById(R.id.textview1); Geocoder geocoder = new Geocoder(Main.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); } } catch (Exception e) { tv1.setText(" 轉換失敗 "); } }});

result

實機 模擬器

建立 showlocation 方法

// 顯示座標點private void showloaction(double d,double e,String title, String snip){ LatLng CTU = new LatLng(d, e); // 取得地圖物件 map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); // 建立紅色氣球標示 Marker mk = map.addMarker(new MarkerOptions().position(CTU).title(title).snippet(snip)); // 設定縮放大小是 16 ,且將標示點放在正中央 map.moveCamera(CameraUpdateFactory.newLatLngZoom(CTU, 16));}

呼叫 showlocation 方法

呼叫 showlocation 方法 Button btn_address_to_geo=(Button)findViewById(R.id.button3); btn_address_to_geo.setOnClickListener(new Button.OnClickListener() { public void onClick(View arg0) { try { EditText inputaddress=(EditText)findViewById(R.id.editText1); tv1=(TextView)findViewById(R.id.textview1); Geocoder geocoder = new Geocoder(Main.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); showloaction((double)(addr.getLatitude()), (double)(addr.getLongitude()),inputaddress.getText().toString(),""); } } catch (Exception e) { tv1.setText(" 轉換失敗 "); } } });

AVD 多數執行有問題,最好使用手機測試

輸入地址

轉換地址成座標

座標

顯示座標點

不用註冊 Google Maps API 也可以使用 Intent

public class MapIntent extends Activity {

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri uri=Uri.parse("geo:24.06660656734983,120.54975986480713"); Intent it=new Intent(Intent.ACTION_VIEW,uri); startActivity(it);}}

顯示 Google Maps 地圖

利用 Intent 玩 Google Maps

Google Maps street view

– Uri uri=Uri.parse("google.streetview:cbll=46.813812,-71.207378&cbp=1,99.56,,1,-5.27&mz=21");

只支援美加地區

AVD 是看不到的!

更多 Google Maps

• 路徑規劃

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textview1" android:text="" android:layout_width="wrap_content" android:layout_height="wrap_content"/><fragment android:layout_weight="1" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.SupportMapFragment"/></LinearLayout>

加入對應的 xml

AndroidManiFest.xml

• 需要開放以下權限– <uses-permission

android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>

– <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

偵測是否開啟 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

private LocationManager mLocationManager;

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 String mLocationPrivider="";private Location mLocation;

宣告物件

補充說明

tv_show_gps=(TextView)findViewById(R.id.textview1); createCancelProgressDialog(" 定位中 "," 定位中 .. 請稍待! "," 取消 "); try{ // 如果沒有開啟 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 mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); // Provider 初始化 getLocationPrivider(); // 設定 GPS 的 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"); }

}catch(Exception e){ new AlertDialog.Builder(GPS.this) .setTitle(" 系統訊息 ") .setMessage("無法取得 GPS 座標 ") .setPositiveButton("確認 ",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub MyDialog.dismiss(); } }) .show(); }

// 取得 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) { }};//-----------------偵測位置改變

// 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;}

// 產生定位中視窗 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(); }

透過 ddms 送出模擬 GPS 座標到AVD

需要<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

取得 GPS 訊號後,將其顯示到Google Maps 上

結合前面的 showloaction 方法• 在 onLocationChanged 中加入呼叫

記得加入地圖private GoogleMap map;

稍微修改 showloaction 方法

移除前一個氣球

result

控制旋轉不觸發 oncreate

• AndroidMainfast.xml 中設定允許改變:– <uses-permission

android:name="android.permission.CHANGE_CONFIGURATION" />

• AndroidMainfast.xml 中對要攔截旋轉事件的Activity 加入屬性:– android:configChanges="orientation"

畫路徑-從現在的範例修改LatLng p1; // 出發點LatLng p2; // 結束點

if(mLocation!=null) //第一次顯示{ // 取得速度 double speed=mLocation.getSpeed()/1000*60*60; //原單位是 m/s double altitude = mLocation.getAltitude(); p1 = new LatLng(mLocation.getLatitude(), mLocation.getLongitude()); tv_show_gps.setText(“緯度:” + formatgeo(mLocation.getLatitude()) + " 經度: " + formatgeo(mLocation.getLongitude()) + " 海拔: " + altitude + " m 速度: " + formatspeed(speed) + "km/h");}

加入成全域

加入第一個點

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"); p2 = new LatLng(location.getLatitude(), location.getLongitude()); showloaction((double)(location.getLatitude()), (double)(location.getLongitude()),"目前 GPS座標點 ",""); p1=p2; MyDialog.dismiss(); // 結束進度 }

取得結束點畫線

將結束點變成出發點

// 顯示座標點private void showloaction(double d,double e,String title, String snip){ LatLng CTU = new LatLng(d, e); // 取得地圖物件 map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); // 建立紅色氣球標示 if(mk != null) mk.remove(); mk = map.addMarker(new MarkerOptions().position(CTU).title(title).snippet(snip)); // 設定縮放大小是 16 ,且將標示點放在正中央 //map.moveCamera(CameraUpdateFactory.newLatLngZoom(CTU, 16)); PolylineOptions line=new PolylineOptions().add(p1,p2).width(5).color(Color.BLUE); map.addPolyline(line); map.moveCamera(CameraUpdateFactory.newLatLngZoom(p2, 16));}

加入畫線

top related