Lah*_*ima 17 android google-maps google-maps-android-api-2
我想在我的Android应用程序中显示两个位置之间的行车路线.我想在路段之上绘制路线.
堆栈溢出本身有几个答案,所有这些都使用相同的方法.使用Google Directions API获取从起点到目的地的路线,并在返回的点上绘制折线.以下是使用此方法的一些答案.
但是,上述方法的问题是,当道路不直时,黎明死记硬背并不总是在道路上,因为方向API只返回您需要从一条道路转向另一条道路的点(在交叉点处).它没有在同一道路段的弯道中给出点数细节.因此,当我在道路有很多弯道的区域使用上述方法时,几乎总是绘制的路线不在路段之上.
我找到了这个答案,它使用javascript API做我需要做的事情.在这个解决方案中,绘制的路线很好地遵循道路,类似于谷歌地图Android应用程序.有人知道这是否可以在Android应用程序中实现?
谷歌地图Android应用程序可以很好地绘制从一个点到另一个点的路线,保持路线在道路上.有谁知道谷歌地图是如何做到这一点的?它是否使用任何其他未公开的API?
xom*_*ena 37
实际上,您可以使用Directions API网络服务提供的结果在Google Maps Android API中绘制精确路线.如果您阅读Directions API的文档,您会看到该响应包含有关路径支路和步骤的信息.每个步骤都有一个字段polyline,在文档中描述为
折线包含单个点对象,该对象包含步骤的编码折线表示.该折线是该步骤的近似(平滑)路径.
因此,解决您的问题的主要思想是从Directions API获取响应,循环路径支路和步骤,为每个步骤获取编码折线并将其解码为坐标列表.完成后,您将获得所有坐标的列表,这些坐标使路线更加复杂,而不仅仅是每个步骤的起点和终点.
为简单起见,我建议将Java客户端库用于Google Maps Web服务:
https://github.com/googlemaps/google-maps-services-java
使用此库可以避免为折线实现自己的异步任务和解码功能.阅读文档以了解如何在项目中添加客户端库.
在Gradle中应该是类似的东西
compile 'com.google.maps:google-maps-services:(insert latest version)'
compile 'org.slf4j:slf4j-nop:1.7.25'
Run Code Online (Sandbox Code Playgroud)
我创建了一个简单的例子来演示它是如何工作的.看看我在代码中的评论
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private String TAG = "so47492459";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng barcelona = new LatLng(41.385064,2.173403);
mMap.addMarker(new MarkerOptions().position(barcelona).title("Marker in Barcelona"));
LatLng madrid = new LatLng(40.416775,-3.70379);
mMap.addMarker(new MarkerOptions().position(madrid).title("Marker in Madrid"));
LatLng zaragoza = new LatLng(41.648823,-0.889085);
//Define list to get all latlng for the route
List<LatLng> path = new ArrayList();
//Execute Directions API request
GeoApiContext context = new GeoApiContext.Builder()
.apiKey("YOUR_API_KEY")
.build();
DirectionsApiRequest req = DirectionsApi.getDirections(context, "41.385064,2.173403", "40.416775,-3.70379");
try {
DirectionsResult res = req.await();
//Loop through legs and steps to get encoded polylines of each step
if (res.routes != null && res.routes.length > 0) {
DirectionsRoute route = res.routes[0];
if (route.legs !=null) {
for(int i=0; i<route.legs.length; i++) {
DirectionsLeg leg = route.legs[i];
if (leg.steps != null) {
for (int j=0; j<leg.steps.length;j++){
DirectionsStep step = leg.steps[j];
if (step.steps != null && step.steps.length >0) {
for (int k=0; k<step.steps.length;k++){
DirectionsStep step1 = step.steps[k];
EncodedPolyline points1 = step1.polyline;
if (points1 != null) {
//Decode polyline and add points to list of route coordinates
List<com.google.maps.model.LatLng> coords1 = points1.decodePath();
for (com.google.maps.model.LatLng coord1 : coords1) {
path.add(new LatLng(coord1.lat, coord1.lng));
}
}
}
} else {
EncodedPolyline points = step.polyline;
if (points != null) {
//Decode polyline and add points to list of route coordinates
List<com.google.maps.model.LatLng> coords = points.decodePath();
for (com.google.maps.model.LatLng coord : coords) {
path.add(new LatLng(coord.lat, coord.lng));
}
}
}
}
}
}
}
}
} catch(Exception ex) {
Log.e(TAG, ex.getLocalizedMessage());
}
//Draw the polyline
if (path.size() > 0) {
PolylineOptions opts = new PolylineOptions().addAll(path).color(Color.BLUE).width(5);
mMap.addPolyline(opts);
}
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(zaragoza, 6));
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,对于Web服务,您必须创建单独的API密钥,具有Android应用限制的API密钥将无法与Web服务一起使用.
我的示例的结果显示在屏幕截图中
您也可以从中下载完整的示例项目
https://github.com/xomena-so/so47492459
不要忘记用你的API替换API密钥.
我希望这有帮助!
从 Google 控制台启用 Direction API。API_KEY在GetPathFromLocation.java课堂上替换
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.PolylineOptions;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class GetPathFromLocation extends AsyncTask<String, Void, PolylineOptions> {
private String TAG = "GetPathFromLocation";
private String API_KEY = "Place_Your_API_Key";
private LatLng source, destination;
private DirectionPointListener resultCallback;
public GetPathFromLocation(LatLng source, LatLng destination, DirectionPointListener resultCallback) {
this.source = source;
this.destination = destination;
this.resultCallback = resultCallback;
}
public String getUrl(LatLng origin, LatLng dest) {
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
String sensor = "sensor=false";
String parameters = str_origin + "&" + str_dest + "&" + sensor;
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters + "&key=" + API_KEY;
return url;
}
@Override
protected PolylineOptions doInBackground(String... url) {
String data;
try {
InputStream inputStream = null;
HttpURLConnection connection = null;
try {
URL directionUrl = new URL(getUrl(source, destination));
connection = (HttpURLConnection) directionUrl.openConnection();
connection.connect();
inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer stringBuffer = new StringBuffer();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
data = stringBuffer.toString();
bufferedReader.close();
} catch (Exception e) {
Log.e(TAG, "Exception : " + e.toString());
return null;
} finally {
inputStream.close();
connection.disconnect();
}
Log.e(TAG, "Background Task data : " + data);
JSONObject jsonObject;
List<List<HashMap<String, String>>> routes = null;
try {
jsonObject = new JSONObject(data);
// Starts parsing data
DirectionHelper helper = new DirectionHelper();
routes = helper.parse(jsonObject);
Log.e(TAG, "Executing Routes : "/*, routes.toString()*/);
ArrayList<LatLng> points;
PolylineOptions lineOptions = null;
// Traversing through all the routes
for (int i = 0; i < routes.size(); i++) {
points = new ArrayList<>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = routes.get(i);
// Fetching all the points in i-th route
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);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(10);
lineOptions.color(Color.BLUE);
Log.e(TAG, "PolylineOptions Decoded");
}
// Drawing polyline in the Google Map for the i-th route
if (lineOptions != null) {
return lineOptions;
} else {
return null;
}
} catch (Exception e) {
Log.e(TAG, "Exception in Executing Routes : " + e.toString());
return null;
}
} catch (Exception e) {
Log.e(TAG, "Background Task Exception : " + e.toString());
return null;
}
}
@Override
protected void onPostExecute(PolylineOptions polylineOptions) {
super.onPostExecute(polylineOptions);
if (resultCallback != null && polylineOptions != null)
resultCallback.onPath(polylineOptions);
}
}
Run Code Online (Sandbox Code Playgroud)
方向助手.java
import com.google.android.gms.maps.model.LatLng;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DirectionHelper {
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;
}
//Method to decode polyline points
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;
}
}
Run Code Online (Sandbox Code Playgroud)
方向点监听器.java
import com.google.android.gms.maps.model.PolylineOptions;
public interface DirectionPointListener {
public void onPath(PolylineOptions polyLine);
}
Run Code Online (Sandbox Code Playgroud)
在 Activity 或 Fragment 中使用
LatLng source = new LatLng(xx.xxxx, yy.yyyy);
LatLng destination = new LatLng(xx.xxxx, yy.yyyy);
new GetPathFromLocation(source, destination, new DirectionPointListener() {
@Override
public void onPath(PolylineOptions polyLine) {
yourMap.addPolyline(polyLine);
}
}).execute();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38144 次 |
| 最近记录: |