Google Map API v2 - Get Driving Distance from Current Location to Known Locations

爷,独闯天下 提交于 2019-12-03 21:54:34

Here's an update of your existing code:

// Executes in UI thread, after the parsing process
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> result)  
{
    if (result.size() < 1) 
    {
        Toast.makeText(getActivity(), "No Points", Toast.LENGTH_SHORT).show();
        return;
    }

    TextView tv1 = (TextView) getActivity().findViewById(R.id.location1);
    TextView tv2 = (TextView) getActivity().findViewById(R.id.location2);
    TextView tv3 = (TextView) getActivity().findViewById(R.id.location3);
    TextView tv4 = (TextView) getActivity().findViewById(R.id.location4);

    TextView[] views = {tv1, tv2, tv3, tv4};


    // Traversing through all the routes
    for (int i = 0; i < result.size(); i++) 
    {
        // Fetching i-th route
        List<HashMap<String, String>> path = result.get(i);
        String distance = "No distance";

        // 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)  
            {
                distance = point.get("distance");
                continue;
            }
        }

        // Set text
        views[i].setText(distance);
    }
}

This code makes a not-so-good assumption: It assumes that the size of result is the same size as views, which in your case should be 4. When you run this code, you may get an IndexOutOfBounds error if you have more than 4 results (which shouldn't happen). Eventually you will want to verify that the size of result is 4, or the number of TextView's you have. If you have any questions or this doesn't work right, just let me know :)

EDIT: To get all distances at once, you can modify your DownloadTask to take in multiple URL's.

Change class definition:

private class DownloadTask extends AsyncTask<String, Void, ArrayList<String>>

This says that your background operation will return a list of String's.

Modified doInBackground(), which now can process multiple URL's:

// Downloading data in non-ui thread
@Override
protected ArrayList<String> doInBackground(String... urlList) 
{
    try 
    {
        ArrayList<String> returnList = new ArrayList<String>();
        for(String url : urlList)
        {
            // Fetching the data from web service
            String data = Locations.this.downloadUrl(url);
            returnList.add(data);
        }

        return returnList;
    } 
    catch (Exception e) 
    {
        Log.d("Background Task", e.toString());
        return null; // Failed, return null
    }
}

Then you onPostExecute() becomes

// Executes in UI thread, after the execution of
// doInBackground()
@Override
protected void onPostExecute(ArrayList<String> results) 
{
    super.onPostExecute(results);

    ParserTask parserTask = new ParserTask();

    // Invokes the thread for parsing the JSON data
    parserTask.execute(results);

}

Now, you will have to modify your ParserTask code to take in a list of JSON Strings, and not just one JSON String. Just change your ParserTask input parameters and put everything inside a for loop to loop through each JSON String. You will also have to modify the parameter of onPostExecute() to take in a List of whatever is there already, so that way it doesn't process one result, but a list of results. I can't show you those modifications here because it would be way too long, and then there would be no challenge for you :)

EDIT TWO: In getLastLocation() you're only calling DownloadTask with one URL, but you should put four URL's like this downloadTask.execute(url1, url2, url3, url4). Also, since ParserTask still only processes one JSON String, you should take out the four TextView's and the array looping out of the onPostExecute(). To tell the ParserTask which TextView to populate, add a constructor to ParserTask which takes in a TextView as a parameter. Then make an instance variable within ParserTaskthat is assigned in the constructor and used in onPostExecute() to display the distance.

Then, take that TextView array stuff I gave you before and put it in the onPostExecute() of DownloadTask. When you loop through the String results, also loop through the TextView array and pass in the TextView in the ParserTask constructor.

Basically, you're adding a constructor in the ParserTask to tell it which TextView to draw on. When your DownloadTask is finished, you pass it the right TextView for the URL. For example, R.id.location3 for the third URL.

public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
        * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;

return dist;
}

this method will calculate distance from one location to another, the accuracy is depend upon the frequency of lat,lng. More lat,lat more accurate. Remember there is difference in distance and displacement.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!