Android + Google Maps

Similar documents
多媒體應用 13 新增專案並完成版面配置 <ExMusic01> <activity_main.xml> ImageView ID imgplay ImageView ID imgstop ImageView ID imgfront TextView ID txtsong TextView ID t

Android Service

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

Android Fragment

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

Microsoft Word - PHP7Ch01.docx

untitled

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

建立Android新專案

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e

投影片 1

RecyclerView and CardVew

x MapReduce A Italic URL Constant width Constant width bold Constant width italic 這個圖示代表提示或建議 這個圖示代表一般註解

Dynamic Layout in Android

Microsoft Word - 01.DOC

Android + WebService

chp6.ppt

Android + NFC

建立Android新專案

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

Microsoft PowerPoint - 12 特色开发.ppt [兼容模式]

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

幻灯片 1

《大话设计模式》第一章

JavaIO.PDF

untitled

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

Java

3.1 num = 3 ch = 'C' 2

Chapter 9: Objects and Classes

CC213

EJB-Programming-4-cn.doc

概述

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

新版 明解C++入門編

Android Android Android SDK iv

untitled

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 :

<4D F736F F D BB4FC657A4E5A4C6BEC7B34EACE3B051B77CC4B3B57BAAED2E646F6378>

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之

RxJava

untitled

Microsoft PowerPoint - VB14.ppt

使用MapReduce读取XML文件

建立Android新專案

基于CDIO一体化理念的课程教学大纲设计

untitled

建模与图形思考

untitled

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

建模与图形思考

Microsoft Word - A _ doc

國立勤益科技大學 電子工程系 四技日實務專題報告 題目 : 導航人物 APP 指導教授 : 陳英傑 專題生 : 方懋穎 中華民國一百零六年六月 1

任務二 : 產生 20 個有炸彈的磚塊, 放在隨機的位置編輯 Block 類別的程式碼 import greenfoot.; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) Write a description of class

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

9, : Java 19., [4 ]. 3 Apla2Java Apla PAR,Apla2Java Apla Java.,Apla,,, 1. 1 Apla Apla A[J ] Get elem (set A) A J A B Intersection(set A,set B) A B A B

The golden pins of the PCI card can be oxidized after months or years

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

Microsoft PowerPoint - Lab 2-3 Android Google Maps.ppt [相容模式]

中南大学第二届软件创新大赛

untitled

Microsoft Word zw

FY.DOC

IoC容器和Dependency Injection模式.doc

EJB-Programming-3.PDF

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

2 WF 1 T I P WF WF WF WF WF WF WF WF 2.1 WF WF WF WF WF WF

目录 一 功能介绍 功能列表 使用限制...3 二 Android studio 如何导入 SDK SDK 文件结构 导入必要文件 工程配置...6 三 调用 SDK 初始化 如何开始预览...1

威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 號 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民

目 录

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

Microsoft Word - ch04三校.doc

ebook39-6

全国计算机技术与软件专业技术资格(水平)考试

實作SQLiteOpenHelper類別

運算子多載 Operator Overloading

untitled

javaexample-02.pdf

ebook14-4

FileMaker 16 ODBC 和 JDBC 指南

基于ECO的UML模型驱动的数据库应用开发1.doc

JBuilder Weblogic

计 算 机 系 统 应 用 年 第 25 卷 第 4 期 线 程 的 复 用 [2,3]. 通 常 情 况 下, 服 务 器 端 程 序 在 启 动 时 创 建 若 干 数 量 的 线 程 对 象 并 缓 存 起 来, 此 时 它 们 处 于

Chapter 9: Objects and Classes

ebook39-5

coverage2.ppt

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj

_12-17.QXD

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

Microsoft Word - 第1章 Android基本概念.docx

(Microsoft Word - \244g\246a\247B\244\275\253H\245\365\244\247\275\325\254d\254\343\250s doc)

0511-Android程式之GPS應用_專題週記4

1. 访 问 最 新 发 行 公 告 信 息 jconnect for JDBC 访 问 最 新 发 行 公 告 信 息 最 新 版 本 的 发 行 公 告 可 以 从 网 上 获 得 若 要 查 找 在 本 产 品 发 布 后 增 加 的 重 要 产 品 或 文 档 信 息, 请 访

掌盟 SoEasy SDK 开发者帮助文档 1. 接入前项目检查 根据游戏接入后出现的问题, 对游戏项目做以下几点要求 : a) AndroidManifest.xml 中 android:targetsdkversion="19" b) 如果 AndroidManifest.xml 有 insta

C 1

云数据库 RDS SDK

概述

Guava学习之Resources

Transcription:

Android + Google Maps 建國科技大學資管系饒瑞佶 2017/3 V1

建立新 Android 專案

選擇 Google Maps Activity

專案建立後 檔案 google_maps_api.xml 內有申請 API Key 的網址 最後 API KEY 填入這

申請 API Key

建立憑證

完成 API KEY 建立 專案要用的 API Key

確認資訊

將 API Key 貼入專案內的 google_maps_api.xml

AndroidManifest.xml

準備一個座標點 緯度 經度

activity_maps.xml

MainActivity.java 取得 layout 上對應的 fragment

onmapready- 當 Google Map 服務載入後 取得 Google Map 物件

將地標改成前面取得的座標 改成我們自己的預設在雪梨

執行如果有錯誤 修改 build.gradle(app) 加入 :multidexenabled = true

執行 確認基本的地圖元件沒問題

放大地圖 mmap.animatecamera(cameraupdatefactory.zoomto(16));

執行

加入功能選項

旋轉地圖時出現 執行

改用自訂 marker 原來預設的紅氣球

LatLng place = new LatLng(24.066516, 120.549871); // 建國科大 BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.school); MarkerOptions markeroptions = new MarkerOptions(); markeroptions.position(place).title(" 學校 ").snippet(" 建國科技大學 ").icon(icon); mmap.addmarker(markeroptions);

執行

畫線

// 畫線 ArrayList<LatLng> points= new ArrayList<>(); // 所有點集合 PolylineOptions lineoptions = new PolylineOptions(); // 多邊形 double lat = 24.066516; // 建國科大 double lng = 120.549871; LatLng position = new LatLng(lat, lng); points.add(position); // 加入座標點到 points 物件 double lat1 = 24.050731; // 鹿港龍山寺 double lng1 = 120.435614; LatLng position1 = new LatLng(lat1, lng1); points.add(position1); // 加入座標點到 points 物件 lineoptions.addall(points); // 加入所有座標點到多邊形 lineoptions.width(10); lineoptions.color(color.red); if(lineoptions!= null) { mmap.addpolyline(lineoptions); // 畫出多邊形 else { Log.d("onPostExecute","draw line error!");

執行

setonmapclicklistener 設定地圖點擊事件

加入點擊後儲存座標點的 ArrayList

加入點擊地圖後, 在點擊位置標出 marker

// 設定點擊事件 mmap.setonmapclicklistener(new GoogleMap.OnMapClickListener() { @Override public void onmapclick(latlng latlng) { if (MarkerPoints.size() > 1) { // 超過一個點時, 清空地圖版面 MarkerPoints.clear(); mmap.clear(); // 將點擊位置加入 MarkerPoints MarkerPoints.add(latLng); // 加入 marker 設定 MarkerOptions options = new MarkerOptions(); options.position(latlng); // 設定地點 if (MarkerPoints.size() == 1) { // 起始點顏色 options.icon(bitmapdescriptorfactory.defaultmarker(bitmapdescriptorfactory.hue_green)); else if (MarkerPoints.size() == 2) { // 後續點的顏色 options.icon(bitmapdescriptorfactory.defaultmarker(bitmapdescriptorfactory.hue_red)); // 將點畫在地圖上 mmap.addmarker(options); );

改進兩點間連線, 依照路畫線, 而非直線

// 依照實際路畫出路徑圖 if (MarkerPoints.size() >= 2) { // 需要確定有 2 點 LatLng origin = MarkerPoints.get(0); // 第 1 個點 LatLng dest = MarkerPoints.get(1); // 第 2 個點 // 取得 Google Directions API String url = geturl(origin, dest); // 組合呼叫 API 需要的 URL FetchUrl FetchUrl = new FetchUrl(); // 解析 URL 回傳結果 FetchUrl.execute(url); // 移動座標視窗 mmap.movecamera(cameraupdatefactory.newlatlng(origin)); mmap.animatecamera(cameraupdatefactory.zoomto(16));

建立 Google Directions URL

// 取得 Google Directions API private String geturl(latlng origin, LatLng dest) { // 路徑起點 String str_origin = "origin=" + origin.latitude + "," + origin.longitude; // 路徑終點 String str_dest = "destination=" + dest.latitude + "," + dest.longitude; // Sensor enabled String sensor = "sensor=false"; // 建立參數 String parameters = str_origin + "&" + str_dest + "&" + sensor; // 設定輸出格式 String output = "json"; // 建立完整的 URL String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters; return url;

解析 URL 回傳結果 解析 JSON 並畫出路徑

// 解析 URL 回傳結果 private class FetchUrl extends AsyncTask<String, Void, String> { @Override protected String doinbackground(string... url) { // 接收從 Google Directions 回傳的資料 (JSON Format) String data = ""; try { data = downloadurl(url[0]); // 呼叫 downloadurl 取得路徑 json 資料 catch (Exception e) { Log.d("Background Task", e.tostring()); return data; @Override protected void onpostexecute(string result) { super.onpostexecute(result); ParserTask parsertask = new ParserTask(); // 解析 JSON 資料 parsertask.execute(result);

下載 Google Directions 回傳 json 資料

// 下載 Google Directions 回傳 json 資料 private String downloadurl(string strurl) throws IOException { String data = ""; InputStream istream = null; HttpURLConnection urlconnection = null; try { URL url = new URL(strUrl); // 建立 http 連線 urlconnection = (HttpURLConnection) url.openconnection(); // 連線 url urlconnection.connect(); // 讀取資料 istream = urlconnection.getinputstream(); BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); StringBuffer sb = new StringBuffer(); String line = ""; while ((line = br.readline())!= null) { sb.append(line); data = sb.tostring(); br.close(); catch (Exception e) { Log.d("Exception", e.tostring()); finally { istream.close(); urlconnection.disconnect(); return data;

解析 JSON 並畫出路徑 需要 DataParser 類別 接下頁

接下頁

// 解析 JSON 並畫出路徑 private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> { // Parsing the data in non-ui thread @Override protected List<List<HashMap<String, String>>> doinbackground(string... jsondata) { JSONObject jobject; List<List<HashMap<String, String>>> routes = null; try { jobject = new JSONObject(jsonData[0]); DataParser parser = new DataParser(); // DataParser 類別 // 開始解析 routes = parser.parse(jobject); catch (Exception e) { e.printstacktrace(); return routes; 接下頁

@Override protected void onpostexecute(list<list<hashmap<string, String>>> result) { ArrayList<LatLng> points; PolylineOptions lineoptions = null; // 取出路徑 for (int i = 0; i < result.size(); i++) { points = new ArrayList<>(); lineoptions = new PolylineOptions(); List<HashMap<String, String>> path = result.get(i); // 取出路徑上所有點 for (int j = 0; j < path.size(); j++) { HashMap<String, String> point = path.get(j); double lat = Double.parseDouble(point.get("lat")); double lng = Double.parseDouble(point.get("lng")); LatLng position = new LatLng(lat, lng); points.add(position); // 將所有點加入 lineoptions lineoptions.addall(points); lineoptions.width(10); lineoptions.color(color.red); // 畫出路徑 if(lineoptions!= null) { mmap.addpolyline(lineoptions); else { Log.d("onPostExecute","without Polylines drawn");

DataParser 類別 public class DataParser { /** Receives a JSONObject and returns a list of lists containing latitude and longitude */ public List<List<HashMap<String,String>>> parse(jsonobject jobject){ List<List<HashMap<String, String>>> routes = new ArrayList<>() ; JSONArray jroutes; JSONArray jlegs; JSONArray jsteps; try { jroutes = jobject.getjsonarray("routes"); /** Traversing all routes */ for(int i=0;i<jroutes.length();i++){ jlegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs"); List path = new ArrayList<>(); 接下頁

/** Traversing all legs */ for(int j=0;j<jlegs.length();j++){ jsteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps"); /** Traversing all steps */ for(int k=0;k<jsteps.length();k++){ String polyline = ""; polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points"); List<LatLng> list = decodepoly(polyline); /** Traversing all points */ for(int l=0;l<list.size();l++){ HashMap<String, String> hm = new HashMap<>(); hm.put("lat", Double.toString((list.get(l)).latitude) ); hm.put("lng", Double.toString((list.get(l)).longitude) ); path.add(hm); routes.add(path); catch (JSONException e) { e.printstacktrace(); catch (Exception e){ return routes; 接下頁

private List<LatLng> decodepoly(string encoded) { List<LatLng> poly = new ArrayList<>(); int index = 0, len = encoded.length(); int lat = 0, lng = 0; while (index < len) { int b, shift = 0, result = 0; do { b = encoded.charat(index++) - 63; result = (b & 0x1f) << shift; shift += 5; while (b >= 0x20); int dlat = ((result & 1)!= 0? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.charat(index++) - 63; result = (b & 0x1f) << shift; shift += 5; while (b >= 0x20); int dlng = ((result & 1)!= 0? ~(result >> 1) : (result >> 1)); lng += dlng; LatLng p = new LatLng((((double) lat / 1E5)), (((double) lng / 1E5))); poly.add(p); return poly; 接下頁

畫面加入其他物件

加入 TextView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" map:maptype="normal"> <TextView android:text="google Maps 測試 " android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/textview" /> <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.supportmapfragment" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1"/> </LinearLayout>

整合位置服務 Google Play Services Location API GPS 或 WiFi

準備工作 開啟 Android SDK Manager, 檢查 Extras -> Google Play services 是否已經安裝 如果還沒有安裝的話, 勾選並執行安裝的工作

修改或確認 build.gradle(module:app) 是否有 :compile 'com.google.android.gms:play-services:x.x.x 版本會依據寫程式的時間點而不同

修改 ManifestAndroid.xml 加入 : <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> 前面的 Google Maps 服務

修改 ManifestAndroid.xml 加入 : <uses-permission android:name="android.permission.access_coarse_location"/>

Android 取得位置資料 使用 Google Services 下的 Location API 先使用 com.google.android.gms.common.api 套件下的 GoogleApiClient, 連線與使用 Google Services 服務 再使用 com.google.android.gms.location 套件下的 API, 取得裝置目前的位置資訊

複製前面 Google Maps 使用的 Activity 複製前面 Google Maps 使用的 MainActivity.java, 成為新的 GPSMainActivity.java, 讓兩者不會互相干擾 GPSMainActivity.java 中只要保留地圖與 marker 部分程式, 原來畫線與路徑規劃 (Directions API) 部分可以刪除 此處最重要的是取得目前地點座標 (GPS 或 WiFi 網路 ), 將其以 marker 方式顯示到 Google Maps 上

GPSMainActivity.java 中只要保留地圖與 marker 部分程式 取消後面會移到 onresume 取消只保留 mmap

GPSMainActivity.java 加入需要的物件宣告 // Location API // Google API 用戶端物件 private GoogleApiClient googleapiclient; // Location 請求物件 private LocationRequest locationrequest; // 取得裝置目前最新的位置 private Location currentlocation; // 目前位置對應的 marker private Marker currentmarker; 前面的 Google Maps 服務

GPSMainActivity.java 加入需要繼承 GoogleApiClient.ConnectionCallbacks 與 GoogleApiClient.OnConnectionFailedListener 需要加入對應的事件與方法

對應繼承需要加入的 3 個事件與方法

GPSMainActivity.java 加入接收位置更新資訊的繼承 LocationListener 對應繼承需要加入的事件與方法

先使用 com.google.android.gms.common.api 套件下的 GoogleApiClient, 連線與使用 Google Services 服務 建立 Google API client 物件, 並在 oncreate 中呼叫

建立 Google API client 物件 // 建立 Google API client 物件 private synchronized void configgoogleapiclient() { googleapiclient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); 該物件會執行 ConnectionCallbacks 與 OnConnectionFailedListener 兩個繼承對應的 3 個方法

再使用 com.google.android.gms.location 套件下的 API, 取得裝置目前的位置資訊 建立 LocationRequest 物件與呼叫

建立 LocationRequest 物件 // 建立 Location request 物件 private void configlocationrequest() { locationrequest = new LocationRequest(); // 設定讀取位置資訊更新的間隔時間為一秒 (1000ms) locationrequest.setinterval(1000); // 設定從 API 讀取位置資訊的間隔時間為一秒 (1000ms) locationrequest.setfastestinterval(1000); // 設定優先讀取高精確度的位置資訊 (GPS) locationrequest.setpriority(locationrequest.priority_high_accuracy);

修改 onconnected onconnectionfailed 與 onlocationchanged 方法 在 onconnected( 也就是已經連線到 Google Services 後 ) 加入啟動位置更新服務, 會對應到 onlocationchanged 事件 這裡需要搭配 Android 6.0 之後的 Permission 政策做修正

onconnected // 已經連線到 Google Services @Override public void onconnected(@nullable Bundle bundle) { // 啟動位置更新服務, 位置資訊更新的時候, 應用程式會自動呼叫 LocationListener.onLocationChanged if (ActivityCompat.checkSelfPermission(this, android.manifest.permission.access_fine_location)!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.manifest.permission.access_coarse_location)!= PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onrequestpermissionsresult(int requestcode, String[] permissions, // int[] grantresults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; LocationServices.FusedLocationApi.requestLocationUpdates( googleapiclient, locationrequest, GPSMapsActivity.this);

加入 Permission 詢問視窗 Android 6.0 之後的 Permission 政策, 雖然在 Manifest.xml 中有加入 Permissions, 但仍還是要求執行時需要出現詢問視窗, 再次跟使用者確認!

int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION; // 詢問視窗 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); // 接收 permission 詢問視窗回傳值 @Override public void onrequestpermissionsresult(int requestcode, String permissions[], int[] grantresults) { Log.i("GPS", "requestcode=" + requestcode); switch (requestcode) { case 0: { // location if (grantresults.length > 0 && grantresults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the else { // permission denied, boo! Disable the return;

onconnectionfailed 方法

onconnectionfailed 方法 // Google Services 連線失敗,ConnectionResult 參數是連線失敗的資訊 @Override public void onconnectionfailed(@nonnull ConnectionResult connectionresult) { int errorcode = connectionresult.geterrorcode(); // 裝置沒有安裝 Google Play 服務 if (errorcode == ConnectionResult.SERVICE_MISSING) { Toast.makeText(this, " 裝置沒有安裝 Google Play 服務 ",Toast.LENGTH_LONG).show();

onlocationchanged 方法

onlocationchanged 方法 // 位置改變實會觸發,Location 參數是目前的位置 @Override public void onlocationchanged(location location) { currentlocation = location; Log.i("GPS", "onlocationchanged"); // 取得目前位置 LatLng latlng = new LatLng(location.getLatitude(), location.getlongitude()); // 設定目前位置的 marker if (currentmarker == null) { currentmarker = mmap.addmarker(new MarkerOptions().position(latLng)); else { currentmarker.setposition(latlng); // 移動地圖到目前的位置 mmap.movecamera(cameraupdatefactory.newlatlng(latlng)); // 放大地圖 16 倍 mmap.animatecamera(cameraupdatefactory.zoomto(16));

加入 onresume onpause 與 onstop @Override protected void onresume() { super.onresume(); if (mmap == null) { // 取得地圖 ((SupportMapFragment) getsupportfragmentmanager(). findfragmentbyid(r.id.map)).getmapasync(this); // 連線到 Google API 用戶端 if (!googleapiclient.isconnected()) { Log.i("GPS", "onresume"); googleapiclient.connect();

@Override protected void onpause() { super.onpause(); // 取消位置請求服務 if (googleapiclient.isconnected()) { LocationServices.FusedLocationApi.removeLocationUpdates( googleapiclient, this); @Override protected void onstop() { super.onstop(); // 移除 Google API 用戶端連線 if (googleapiclient.isconnected()) { googleapiclient.disconnect();

執行 oncreate onresume onconnected onlocationchanged onresume: 取得地圖與 GoogleApiClient onconnected: 請求連線與使用 Google Services 服務 onlocationchanged: 取得最新的位置

執行