如何在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编程中获得两个地理点之间的精确路线的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android上的两个地理点之间绘制路线

Android:查找两个地理点之间的距离

如何使用数据库(mysql)中的gps位置在两个地理点之间找到pople?

如何找到地图中两个地理点之间的正确距离?

如何在从 ListView 项获取的两个地理点之间绘制标记和路线?

Android 地理围栏(多边形)