如何在android编程中获得两个地理点之间的精确路线
Posted
技术标签:
【中文标题】如何在android编程中获得两个地理点之间的精确路线【英文标题】:How to get precise route between Two geo points in android programming 【发布时间】:2015-06-18 04:44:24 【问题描述】:我正在尝试为自己创建一个谷歌地图示例。目标是计算两个地理点之间的路线。我在试图找出两点之间的路线时遇到了一些问题。一方面,我的地图生成但我在尝试计算距离并在地图上生成路线时遇到了一些错误。请原谅我的编码我是 android 编程的新手。
import android.content.Context;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.text.DecimalFormat;
public class MapsActivity extends FragmentActivity
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
@Override
protected void onResume()
super.onResume();
setUpMapIfNeeded();
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call @link #setUpMap() once when @link #mMap is not null.
* <p/>
* If it isn't installed @link SupportMapFragment (and
* @link com.google.android.gms.maps.MapView MapView) will show a prompt for the user to
* install/update the Google Play services APK on their device.
* <p/>
* A user can return to this FragmentActivity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not
* have been completely destroyed during this process (it is likely that it would only be
* stopped or paused), @link #onCreate(Bundle) may not be called again so we should call this
* method in @link #onResume() to guarantee that it will be called.
*/
private void setUpMapIfNeeded()
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null)
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null)
setUpMap();
/**
* This is where we can add markers or lines, add listeners or move the camera. In this case, we
* just add a marker near Africa.
* <p/>
* This should only be called once and when we are sure that @link #mMap is not null.
*/
private void setUpMap()
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").snippet("Snippet"));
// Enable MyLocation Layer of Google Map
mMap.setMyLocationEnabled(true);
// Get LocationManager object from System Service LOCATION_SERVICE
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Create a criteria object to retrieve provider
Criteria criteria = new Criteria();
// Get the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
// Get Current Location
Location myLocation = locationManager.getLastKnownLocation(provider);
// set map type
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// Get latitude of the current location
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null)
double longitude = location.getLongitude();
double latitude = location.getLatitude();
// Get longitude of the current location
// Create a LatLng object for the current location
LatLng latLng = new LatLng(latitude, longitude);
// Show the current location in Google Map
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
// Zoom in the Google Map
//LatLng myCoordinates = new LatLng(latitude, longitude);
//CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(myCoordinates, 20);
//mMap.animateCamera(yourLocation);
mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("You are here!").snippet("Consider yourself located"));
double fromLat = 49.85, fromLon = 24.016667;
double toLat = 50.45, toLon = 30.523333;
CalculationByDistance(fromLat,toLat);
public double CalculationByDistance(LatLng StartP, LatLng EndP)
int Radius = 6371;// radius of earth in Km
double lat1 = StartP.latitude;
double lat2 = EndP.latitude;
double lon1 = StartP.longitude;
double lon2 = EndP.longitude;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
public void onFinish()
// Your code here to do something after the Map is rendered
【问题讨论】:
【参考方案1】:首先,您需要使用Google Directions API 来获取您希望在地图上绘制的一组点。调用 web 服务并返回结果后,您必须解析类似于 this 的 json。
您想要的点在 route->legs->steps->polyline->points 中,并且它们已被编码,因此您需要使用可以找到 here 的代码来解码它们。
此时,正如 Neal 指出的那样,您需要获取这些点并将它们添加到 PolylineOptions 并将它们添加到地图中。
【讨论】:
【参考方案2】:您的函数CaculationByDistance
接受LatLng
类型变量。所以尝试改变:
double fromLat = 49.85, fromLon = 24.016667;
double toLat = 50.45, toLon = 30.523333;
收件人:
LatLng fromLatLng = new LatLng(49.85, 24.016667);
LatLng toLatLng = new LatLng(50.45, 30.523333);
那么你的函数应该可以工作了:
CalculationByDistance(fromLatLng,toLatLng);
【讨论】:
【参考方案3】:求两点之间的准确距离(跑步距离) 首先从谷歌获取网址,像这样,而不是查找距离
在 mainActivity 中添加这个
String url = getDirectionsUrl(fromLatLng, toLatLng);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
类 getDirectionsURL
private String getDirectionsUrl(LatLng origin,LatLng dest)
// Origin of route
String str_origin = "origin="+origin.latitude+","+origin.longitude;
// Destination of route
String str_dest = "destination="+dest.latitude+","+dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin+"&"+str_dest+"&"+sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
return url;
类查找距离
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String>
// Downloading data in non-ui thread
@Override
protected String doInBackground(String... url)
// For storing data from web service
String data = "";
try
// Fetching the data from web service
data = downloadUrl(url[0]);
catch(Exception e)
Log.d("Background Task",e.toString());
return data;
// Executes in UI thread, after the execution of
// doInBackground()
@Override
protected void onPostExecute(String result)
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
/** A class to parse the Google Places in JSON format */
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]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
catch(Exception e)
e.printStackTrace();
return routes;
// Executes in UI thread, after the parsing process
@SuppressWarnings("unused")
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> result)
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
String distance = "";
String duration = "";
if(result.size()<1)
Toast.makeText(getBaseContext(), "No Points", Toast.LENGTH_SHORT).show();
return;
// Traversing through all the routes
for(int i=0;i<result.size();i++)
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.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);
if(j==0) // Get distance from the list
distance = (String)point.get("distance");
continue;
else if(j==1) // Get duration from the list
duration = (String)point.get("duration");
continue;
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(2);
lineOptions.color(Color.RED);
Log.e("Distance: "+distance , "Duration: "+duration);
tvDistanceDuration.setText("Distance: "+distance + ", Duration: "+duration);
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from 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)
Log.d("Exception while downloading url", e.toString());
finally
iStream.close();
urlConnection.disconnect();
return data;
这是一个获取当前位置的类
使用
调用它LatLng origin = getCurrentLocation();
并在您调用getDirectionsUrl
类时通过这些原点
private LatLng getCurrentLocation()
// Do a null check to confirm that we have not already instantiated the
// map.
if (googleMap == null)
// Try to obtain the map from the SupportMapFragment.
googleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map)).getMap();
googleMap.setMyLocationEnabled(true);
// Check if we were successful in obtaining the map.
if (googleMap != null)
googleMap
.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener()
@Override
public void onMyLocationChange(Location arg0)
googleMap.addMarker(new MarkerOptions()
.position(
new LatLng(arg0.getLatitude(),
arg0.getLongitude()))
.title("You're Here"));
latlng = new LatLng(arg0.getLatitude(), arg0
.getLongitude());
CameraPosition cameraPosition = new CameraPosition(
latlng, 12, 0, 0);
Geocoder geocoder = new Geocoder(
getApplicationContext(), Locale.ENGLISH);
List<Address> addresses;
try
addresses = geocoder.getFromLocation(
arg0.getLatitude(),
arg0.getLongitude(), 1);
if (addresses != null
&& addresses.size() > 0)
Address address = addresses.get(0);
country = address.getCountryName();
latitute = arg0.getLatitude();
longitude = arg0.getLongitude();
Log.e("latitude", latitute+"");
Log.e("longitude", longitude+"");
latSource=latitute;
longSource=longitude;
catch (IOException e)
e.printStackTrace();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition),
4000, null);
googleMap.setOnMyLocationChangeListener(null);
);
return new LatLng(latitute, longitude);
【讨论】:
感谢您的回答,但我想使用位置管理器生成我的 gps 并计算到某个固定位置的方向 你能说得更具体点吗,你的意思是你想用位置管理器找出你的位置,然后计算某个随机点到你当前位置的距离...??? 是的。我想计算距离并显示到那个随机点的路线。 我已编辑答案请检查。以上是关于如何在android编程中获得两个地理点之间的精确路线的主要内容,如果未能解决你的问题,请参考以下文章
如何使用数据库(mysql)中的gps位置在两个地理点之间找到pople?