自製導航

public class Map extends FragmentActivity implements LocationListener {

private LocationManager loctionManager;

private GoogleMap gMap;

private final LatLng destination = new LatLng(23.737958, 120.50840399999993);

private LatLng outset = null;

private MarkerOptions EndMarket, StartMarket;

private String bestProvider = LocationManager.GPS_PROVIDER;

private boolean getGPSService = true;

@Override

protected void onCreate(Bundle arg0) {

super.onCreate(arg0);

Uri uri = Uri.parse("geo:25.047192, 121.516981"); //經緯度

final Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,

WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

setContentView(R.layout.map);

SupportMapFragment sFragment = (SupportMapFragment) this

.getSupportFragmentManager().findFragmentById(R.id.map);

gMap = sFragment.getMap();

// 設定地圖類型:Normal(典型);Hybrid(混合衛星照片及道路);Satellite(衛星);Terrain(地形);None(什麼都沒有);

gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

gMap.setTrafficEnabled(false);

gMap.setMyLocationEnabled(true);

EndMarket = new MarkerOptions();

StartMarket = new MarkerOptions();

updateView(locationServiceInitial());

}

/**

* 更新位置

*

* @param location

*/

public void updateView(Location location) {

if (location != null) {

outset = new LatLng(location.getLatitude(), location.getLongitude());

StartMarket.position(outset);

StartMarket.title("現在位置");

gMap.clear();

EndMarket.position(destination);

EndMarket.title("家");

gMap.addMarker(EndMarket);

gMap.addMarker(StartMarket);

gMap.moveCamera(CameraUpdateFactory.newLatLng(outset));

gMap.animateCamera(CameraUpdateFactory.zoomTo(15));

if (outset != null) {

// 取得URL到Google路線API

String url = getDirectionsUrl(outset, destination);

DownloadTask downloadTask = new DownloadTask();

// 開始下載從Google路線API的JSON數據

downloadTask.execute(url);

}

Toast.makeText(

Map.this,

"現在位置(" + location.getLatitude() + ","

+ location.getLongitude() + ")", Toast.LENGTH_SHORT)

.show();

} else {

Toast.makeText(Map.this, "無法定位現在位置", Toast.LENGTH_SHORT).show();

}

}

/**

* 取得URL到Google路線API

*

* @param origin

* @param dest

* @return

*/

private String getDirectionsUrl(LatLng origin, LatLng dest) {

// 起點

String str_origin = "origin=" + origin.latitude + ","

+ origin.longitude;

// 終點

String str_dest = "destination=" + dest.latitude + "," + dest.longitude;

// 感應器啟用

String sensor = "sensor=false";

// 建立參數到Web Service

String parameters = str_origin + "&" + str_dest + "&" + sensor;

// 輸出格式

String output = "json";

// 構建URL到Web Service

String url = "https://maps.googleapis.com/maps/api/directions/"

+ output + "?" + parameters;

return url;

}

/**

* 解析JSON格式

*

* @author sakata

*

*/

public class ParserTask extends

AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

// 解析在非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]);

DirectionsJSONParser parser = new DirectionsJSONParser();

// Starts parsing data

routes = parser.parse(jObject);

} catch (Exception e) {

e.printStackTrace();

}

return routes;

}

// 執行在UI thread,解析過程後

@Override

protected void onPostExecute(List<List<HashMap<String, String>>> result) {

ArrayList<LatLng> points = null;

PolylineOptions lineOptions = null;

// 通過所有的穿越路線

for (int i = 0; i < result.size(); i++) {

points = new ArrayList<LatLng>();

lineOptions = new PolylineOptions();

// 取第i個途徑

List<HashMap<String, String>> path = result.get(i);

// 在第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(5); // 導航路徑寬度

lineOptions.color(Color.BLUE); // 導航路徑顏色

}

// 在Google地圖繪製折線為第i個路徑

gMap.addPolyline(lineOptions);

}

}

/**

* 從傳遞的url獲取數據

*

* @author sakata

*

*/

public class DownloadTask extends AsyncTask<String, Void, String> {

/**

* 從URL下載JSON資料的方法

*

* @param strUrl

* @return

* @throws IOException

*/

private String downloadUrl(String strUrl) throws IOException {

String data = "";

InputStream iStream = null;

HttpURLConnection urlConnection = null;

try {

URL url = new URL(strUrl);

// 創建一個http連接與URL進行溝通

urlConnection = (HttpURLConnection) url.openConnection();

// 連接URL

urlConnection.connect();

// 從URL讀取數據

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) {

System.out.println("異常在下載時URL發生錯誤 " + e.toString());

} finally {

iStream.close();

urlConnection.disconnect();

}

return data;

}

// 在非UI thread下載數據

protected String doInBackground(String... url) {

// 從Web服務存儲數據

String data = "";

try {

// 從Web服務獲取數據

data = downloadUrl(url[0]);

} catch (Exception e) {

System.out.println("背景工作發生錯誤 " + e.toString());

}

return data;

}

// 執行在UI線程,執行後 doInBackground()

@Override

protected void onPostExecute(String result) {

super.onPostExecute(result);

ParserTask parserTask = new ParserTask();

// 調用解析JSON數據的線程

parserTask.execute(result);

}

}

/**

* 鍵盤事件

*/

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {

loctionManager.removeUpdates((LocationListener) this);

gMap.clear();

Toast.makeText(Map.this, "結束", Toast.LENGTH_SHORT).show();

finish();

}

return super.onKeyDown(keyCode, event);

}

/**

* 位置改變

*/

@Override

public void onLocationChanged(Location location) {

updateView(location);

}

/**

* 停用

*/

@Override

public void onProviderDisabled(String provider) {

}

/**

* 啟用

*/

@Override

public void onProviderEnabled(String provider) {

}

/**

* 狀態改變

*/

@Override

public void onStatusChanged(String provider, int status, Bundle extras) {

}

/**

* 啟用定位模組,使用後記得關閉

*

* @return Location

*/

public Location locationServiceInitial() {

getGPSService = true;

loctionManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 取得系統定位服務

Criteria criteria = new Criteria(); // 資訊提供者選取標準

bestProvider = loctionManager.getBestProvider(criteria, true);

Location location = loctionManager

.getLastKnownLocation(bestProvider); // 使用GPS定位座標

if (location != null) {

return location;

} else {

Toast.makeText(this, "無法定位座標", Toast.LENGTH_LONG).show();

return null;

}

}

@Override

protected void onResume() {

super.onResume();

if (getGPSService) {

updateView(locationServiceInitial());

// 服務提供者、更新頻率毫秒、最短距離、地點改變時呼叫物件

loctionManager.requestLocationUpdates(bestProvider, 1000, 1,

(LocationListener) this);

}

}

@Override

protected void onPause() {

super.onPause();

if (getGPSService) {

loctionManager.removeUpdates((LocationListener) this); // 離開頁面時停止更新

getGPSService = false;

}

}

}

取得定位座標

package tw.com.WeddingInvitation.Set;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import com.google.android.gms.maps.model.LatLng;

public class DirectionsJSONParser {

/**

* 接收一個JSONObject並返回一個列表的列表,包含經緯度

*

* @param jObject

* @return

*/

public List<List<HashMap<String, String>>> parse(JSONObject jObject) {

List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();

JSONArray jRoutes = null;

JSONArray jLegs = null;

JSONArray jSteps = null;

try {

jRoutes = jObject.getJSONArray("routes");

// 經過所有路由器

for (int i = 0; i < jRoutes.length(); i++) {

jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");

ArrayList<HashMap<String, String>> path = new ArrayList<HashMap<String, String>>();

// 經過所有的路徑

for (int j = 0; j < jLegs.length(); j++) {

jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("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);

// 經過所有的點

for (int l = 0; l < list.size(); l++) {

HashMap<String, String> hm = new HashMap<String, String>();

hm.put("lat",

Double.toString(((LatLng) list.get(l)).latitude));

hm.put("lng",

Double.toString(((LatLng) list.get(l)).longitude));

path.add(hm);

}

}

routes.add(path);

}

}

} catch (JSONException e) {

e.printStackTrace();

} catch (Exception e) {

}

return routes;

}

/**

* 解碼折線點的方法

*

* @param encoded

* @return

*/

private List<LatLng> decodePoly(String encoded) {

List<LatLng> poly = new ArrayList<LatLng>();

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;

}

}