谷歌地图API第2版 - 从当前地点驾驶距离已知位置 [英] Google Map API v2 - Get Driving Distance from Current Location to Known Locations

查看:290
本文介绍了谷歌地图API第2版 - 从当前地点驾驶距离已知位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出如何显示从当前位置的行驶距离四个已知位置。我不会在屏幕上显示的地图,我只是想显示有多少英里远的用户目前正在从这些位置。我从一个例子<一href="http://wptrafficanalyzer.in/blog/driving-distance-and-travel-time-duration-between-two-locations-in-google-map-android-api-v2/"相对=nofollow>这里并修改了一点。它带回正确的距离,但我无法弄清楚如何通过在每个4月底的位置,或将它们区分开来。

I'm trying to figure out how to display the driving distance from the current location to four known locations. I'm not showing a map on the screen, I just need to display how many miles away the user currently is from those locations. I took an example from Here and modified it a little. It is bringing back the correct distance but I can't figure out how to pass in each of the 4 end locations, or differentiate between them.

什么我需要做的,为了获得距离各4处,并在不同的TextView显示每个这些距离的?

What do I need to do in order to get the distance to each of the 4 locations and display each of those distances in separate TextViews?

更新的问题:我如何计算每个4 TextViews的距离分开

随着code以下我能够做我想做的第一TextView的

With the code below I'm able to do what I want for the first TextView

的Java

public class Locations extends Fragment {

private Location currentLocation = null;
private LocationManager locationManager;
private GeoPoint currentPoint;

TextView location1;

ArrayList<LatLng> markerPoints;
GoogleMap map;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getLastLocation();
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.activity_locations, container, false);
    ...some other stuff being done here...
    // Return view
    return view;
}

public void getLastLocation(){
    String provider = getBestProvider();
    currentLocation = locationManager.getLastKnownLocation(provider);

    this.markerPoints = new ArrayList<LatLng>();

    LatLng fromPosition = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
    LatLng toPosition = new LatLng(29.633289, -82.305838);
    // These are the other 3 end locations
    LatLng toPosition1 = new LatLng(35.205374, -82.614587);
    LatLng toPosition2 = new LatLng(35.405342, -82.316587);
    LatLng toPosition3 = new LatLng(35.702354, -82.515837);

    Locations.this.markerPoints.add(fromPosition);
    Locations.this.markerPoints.add(toPosition);

    // Getting URL to the Google Directions API
    String url = Locations.this.getDirectionsUrl(fromPosition, toPosition);

    DownloadTask downloadTask = new DownloadTask();

    // Start downloading json data from Google Directions API
    downloadTask.execute(url);

    if(currentLocation != null) {
        setCurrentLocation(currentLocation);
    } else { 
        // do something
    }
}

public String getBestProvider() {
    locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
    Criteria criteria = new Criteria();
    criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
    criteria.setAccuracy(Criteria.NO_REQUIREMENT);
    String bestProvider = locationManager.getBestProvider(criteria, true);
    return bestProvider;
}

public void setCurrentLocation(Location location){
    // Get current location
    int currLatitude = (int) (location.getLatitude()*1E6);
    int currLongitude = (int) (location.getLongitude()*1E6);
    currentPoint = new GeoPoint(currLatitude,currLongitude); 
    // Set current location
    currentLocation = new Location("");
    currentLocation.setLatitude(currentPoint.getLatitudeE6() / 1e6);
    currentLocation.setLongitude(currentPoint.getLongitudeE6() / 1e6);
}

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;
}

/** 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;
}

// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, ArrayList<String>> {
    @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
        }
    }

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

        ParserTask parserTask = new ParserTask();

        for (String url : results) {
            parserTask.execute(url);
        }

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

/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, ArrayList<List<HashMap<String, String>>>> {
    // Parsing the data in non-ui thread
    @Override
    protected ArrayList<List<HashMap<String, String>>> doInBackground(String... jsonData) {
        try {
            ArrayList<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();

            // for (String url : jsonData) {
            for (int i = 0; i < jsonData.length; i++) {
                JSONObject jObject = new JSONObject(jsonData[i]);

                DirectionsJSONParser parser = new DirectionsJSONParser();
                // Starts parsing data
                routes = (ArrayList<List<HashMap<String, String>>>) parser.parse(jObject);
            }
            return routes;
        } catch (Exception e) {
            Log.d("Background task", e.toString());
            return null; // Failed, return null
        }
    }

    // Executes in UI thread, after the parsing process
    @Override
    protected void onPostExecute(ArrayList<List<HashMap<String, String>>> result) {
        if (result.size() < 1) {
            Toast.makeText(getActivity(), "No Points", Toast.LENGTH_LONG).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;
                }
            }

            Log.d("Distance: ", distance);

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

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/location1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/location2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="TextView" />
    <TextView
        android:id="@+id/location3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="TextView" />
    <TextView
        android:id="@+id/location4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="TextView" />
</LinearLayout>
</RelativeLayout>

任何帮助搞清楚了这一点和/或建议,以更好地这个code将大大AP preciated。

Any help figuring this out and/or suggestions to better this code will be greatly appreciated.

推荐答案

下面是对现有的code的更新:

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);
    }
}

这code使一个不那么好的假设:它假设了结果尺寸大小相同的意见,而你的情况应该是4。当你运行这个code,你可以,如果你有4个以上的成果​​得到 IndexOutOfBounds 错误(这不应该发生)。最终你会想验证的结果的大小为4,或的TextView 的数量的你。如果您有任何疑问或本不工作的权利,只是让我知道:)

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

修改:为了让所有的距离一下子,你可以修改 DownloadTask 来参加多个网址

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

更改类的定义:

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

这表示,你的后台操作,将返回字符串列表的。

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

修改 doInBackground(),现在可以处理多个URL的:

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
    }
}

然后你 onPostExecute()变为

// 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);

}

现在,你将不得不修改 ParserTask code采取JSON字符串列表,而不是一个JSON字符串。只要改变你的 ParserTask 输入参数,并把所有东西都在循环遍历每个JSON字符串。你也将不得不修改的参数 onPostExecute()来参加一个列表的一切早已存在,所以这样,它不处理1的结果,但结果的列表。我不能告诉你这些修改在这里,因为这将是太长时间,然后就没有挑战你:)

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

编辑两个: getLastLocation()你只叫 DownloadTask 与一个网址,但你应该放四个URL是这样的 downloadTask.execute(URL1,URL2,URL3,url4)。此外,由于 ParserTask 仍然只处理一个JSON字符串,你应该采取的四个的TextView 的和阵列循环出了 onPostExecute()。说句 ParserTask 其中的TextView 来填充,增加一个构造函数 ParserTask 这需要在的TextView 作为参数。然后,让在 ParserTask 的实例变量分配在构造和使用 onPostExecute()显示的距离。

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.

然后,采取的TextView 数组的东西,我之前给你,并把它放在 onPostExecute() DownloadTask 。当您通过字符串的结果,也依次通过的TextView 阵列,并通过在的TextView 在<$ C环$ C> ParserTask 的构造。

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.

基本上,你要添加的 ParserTask 来告诉它的TextView 上绘制一个构造函数。当你的 DownloadTask 完成后,你通过它的正确的TextView 的URL。例如, R.id.location3 第三个URL。

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.

这篇关于谷歌地图API第2版 - 从当前地点驾驶距离已知位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆